os: Fix BigReq ignoring when another request is pending

Commit cf88363db0 fixed the handling of
BigReq requests that are way too large and handles the case where the
read() syscall returns a short read.  However, it neglected to handle
the case where it returns a long read, which happens when the client
has another request in the queue after the bogus large one.

Handle the long read case by subtracting the smaller of 'needed' and
'gotnow' from oci->ignoreBytes.  If needed < gotnow, simply subtract
the two, leaving gotnow equal to the number of extra bytes read.
Since the code immediately following the (oci->ignoreBytes > 0) block
tries to handle the next request, advance oci->bufptr immediately
instead of setting oci->lenLastReq and letting the next call to
ReadRequestFromClient do it.

Fixes the XTS pChangeKeyboardMapping-3 test.

         CASES TESTS  PASS UNSUP UNTST NOTIU  WARN   FIP  FAIL UNRES  UNIN ABORT
-Xproto    122   389   367     2    19     0     0     0     1     0     0     0
+Xproto    122   389   368     2    19     0     0     0     0     0     0     0

Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Aaron Plattner 2010-10-25 22:01:32 -07:00 committed by Keith Packard
parent cc2c73ddcb
commit c80c41767e

19
os/io.c
View File

@ -410,16 +410,29 @@ ReadRequestFromClient(ClientPtr client)
else else
needed = sizeof(xReq); needed = sizeof(xReq);
} }
oci->lenLastReq = needed;
/* If there are bytes to ignore, ignore them now. */ /* If there are bytes to ignore, ignore them now. */
if (oci->ignoreBytes > 0) { if (oci->ignoreBytes > 0) {
assert(needed == oci->ignoreBytes || needed == oci->size); assert(needed == oci->ignoreBytes || needed == oci->size);
oci->ignoreBytes -= gotnow; /*
needed = gotnow = 0; * The _XSERVTransRead call above may return more or fewer bytes than we
* want to ignore. Ignore the smaller of the two sizes.
*/
if (gotnow < needed) {
oci->ignoreBytes -= gotnow;
oci->bufptr += gotnow;
gotnow = 0;
} else {
oci->ignoreBytes -= needed;
oci->bufptr += needed;
gotnow -= needed;
}
needed = 0;
} }
oci->lenLastReq = needed;
/* /*
* Check to see if client has at least one whole request in the * Check to see if client has at least one whole request in the
* buffer beyond the request we're returning to the caller. * buffer beyond the request we're returning to the caller.