From c80c41767eb101e9dbd8393d8cca7764b4e248a4 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Mon, 25 Oct 2010 22:01:32 -0700 Subject: [PATCH] os: Fix BigReq ignoring when another request is pending Commit cf88363db0ebb42df7cc286b85d30d7898aea840 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 Reviewed-by: Adam Jackson Signed-off-by: Keith Packard --- os/io.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/os/io.c b/os/io.c index fb9f76207..421023807 100644 --- a/os/io.c +++ b/os/io.c @@ -410,16 +410,29 @@ ReadRequestFromClient(ClientPtr client) else needed = sizeof(xReq); } - oci->lenLastReq = needed; /* If there are bytes to ignore, ignore them now. */ if (oci->ignoreBytes > 0) { 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 * buffer beyond the request we're returning to the caller.