Modify FPRead requests so they don’t return more data than will fit in the reply buffer.

This issue arises because ASP requests and replies are limited to a “quantum size” of 4624 bytes even if the amount requested is larger, and the AppleShare FST relies on this behavior in sizing its buffers. DSI does not have this limitation, so it was returning more data than would fit in the buffer.

Also improve error checking, so an error is reported in cases where the buffer is too small.
This commit is contained in:
Stephen Heumann 2017-04-03 16:36:50 -05:00
parent 17421e0ba5
commit 3f40a3190d
3 changed files with 51 additions and 10 deletions

View File

@ -12,7 +12,17 @@
#include "asmglue.h"
#include "cmdproc.h"
static void CompleteCommand(Session *sess, Word result);
typedef struct FPReadRec {
Word CommandCode; /* includes pad byte */
Word OForkRefNum;
LongWord Offset;
LongWord ReqCount;
Byte NewLineMask;
Byte NewLineChar;
} FPReadRec;
#define kFPRead 27
static void EndSession(Session *sess, Boolean callAttnRoutine);
static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec);
@ -40,7 +50,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) {
break;
}
if (i == MAX_SESSIONS) {
CompleteCommand(sess, aspTooManySessions);
CompleteASPCommand(sess, aspTooManySessions);
goto ret;
}
sess = &sessionTbl[i];
@ -67,7 +77,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) {
// one is in progress
if (commandRec->command != aspCloseSessionCommand) {
if (sess->commandPending) {
CompleteCommand(sess, aspSessNumErr);
CompleteASPCommand(sess, aspSessNumErr);
goto ret;
}
sess->commandPending = TRUE;
@ -157,6 +167,37 @@ static void DoSPCommand(Session *sess, ASPCommandRec *commandRec) {
sess->replyBuf = (void*)(commandRec->replyBufferAddr & 0x00FFFFFF);
sess->replyBufLen = commandRec->replyBufferLen;
/*
* If the client is requesting to read more data than will fit in its
* buffer, change the request to ask for only the amount that will fit.
*
* This is necessary because ASP request and reply bodies are limited
* to a "quantum size" of 4624 bytes. Even if more data than that is
* requested, only that amount will be returned in a single reply.
* If the full read count requested is larger, it simply serves as a
* hint about the total amount that will be read across a series of
* FPRead requests. The AppleShare FST relies on this behavior and
* only specifies a buffer size of 4624 bytes for such requests.
*
* DSI does not have this "quantum size" limitation, so the full
* requested amount would be returned but then not fit in the buffer.
* To avoid this, we modify the request to ask only for the amount of
* data that will fit in the buffer. This removes the function of
* hinting about the total read size, but should work OK in practice.
*
* A similar issue could arise with FPEnumerate requests, but it
* actually doesn't in the case of the requests generated by the
* AppleShare FST, so we don't try to address them for now.
*/
if (commandRec->cmdBlkLength == sizeof(FPReadRec)
&& ((FPReadRec*)commandRec->cmdBlkAddr)->CommandCode == kFPRead
&& ntohl(((FPReadRec*)commandRec->cmdBlkAddr)->ReqCount)
> commandRec->replyBufferLen)
{
((FPReadRec*)commandRec->cmdBlkAddr)->ReqCount =
htonl(commandRec->replyBufferLen);
}
/* Mask off high byte of addresses because PFI (at least) may
* put junk in them, and this can cause Marinetti errors. */
SendDSIMessage(sess, &sess->request,
@ -187,7 +228,7 @@ void FlagFatalError(Session *sess, Word errorCode) {
}
if (sess->commandPending) {
CompleteCommand(sess, errorCode);
CompleteASPCommand(sess, errorCode);
}
EndSession(sess, TRUE);
@ -231,11 +272,11 @@ void FinishASPCommand(Session *sess) {
}
complete:
CompleteCommand(sess, 0);
CompleteASPCommand(sess, 0);
}
/* Actions to complete a command, whether successful or not */
static void CompleteCommand(Session *sess, Word result) {
void CompleteASPCommand(Session *sess, Word result) {
SPCommandRec *commandRec;
commandRec = sess->spCommandRec;

View File

@ -15,6 +15,7 @@
extern Session sessionTbl[MAX_SESSIONS];
void DispatchASPCommand(SPCommandRec *commandRec);
void CompleteASPCommand(Session *sess, Word result);
void FinishASPCommand(Session *sess);
void FlagFatalError(Session *sess, Word errorCode);
void PollAllSessions(void);

7
dsi.c
View File

@ -142,12 +142,11 @@ top:
// Maybe we should do something with them?
FinishASPCommand(sess);
} else {
sess->spCommandRec->result = aspSizeErr;
CompleteASPCommand(sess, aspBufErr);
}
} else {
FinishASPCommand(sess);
}
// TODO correct logic for all cases
FinishASPCommand(sess);
return;
}
//Handle a request from the server