Describe the bug
The HTTP state machine does not correctly handle POST requests with an empty body (Content-Length: 0).
When such a request is received, the state remains stuck in HTTP_STATE_POST_RECV, even after calling httpRead() and never transitions to HTTP_POST_POST_SEND.
Expected behavior
For POST requests with an empty body, reading 0 bytes should be enough to transition from HTTP_POST_POST_RECV to HTTP_STATE_POST_SEND immediately.
Additional context
The issue is located in this section of the code: https://github.com/OpenPrinting/libcups/blob/master/cups/http.c#L1903
} else if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODING_CHUNKED) {
...
} else if (http->data_remaining <= 0) {
// No more data to read...
return (0);
}
If data_encoding is HTTP_ENCODING_LENGTH then a remaining size of 0 means there is no data at all so the state shouldn't stay as RECV.
Temporary workaround
The issue can be bypassed by calling httpPeek() after finishing the read loop:
char buffer[254];
ssize_t bytes;
while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0) {
// Body processing here
}
// Force the state machine to progress
httpPeek(http, buffer, sizeof(buffer));
While this is convenient as a workaround, this implies an additionnal caveat for the fix. If httpRead() correctly updates the state then calling
httpPeek(http, buffer, sizeof(buffer));
httpRead(http, buffer, sizeof(buffer));
would yield the expected result if the body contains data. But with an empty body, the state would first transition from POST_RECV to POST_SEND, then HTTP_STATE_STATUS in the call to httpRead() (all states except RECV transition to STATUS).
Describe the bug
The HTTP state machine does not correctly handle POST requests with an empty body (Content-Length: 0).
When such a request is received, the state remains stuck in
HTTP_STATE_POST_RECV, even after callinghttpRead()and never transitions toHTTP_POST_POST_SEND.Expected behavior
For POST requests with an empty body, reading 0 bytes should be enough to transition from
HTTP_POST_POST_RECVtoHTTP_STATE_POST_SENDimmediately.Additional context
The issue is located in this section of the code: https://github.com/OpenPrinting/libcups/blob/master/cups/http.c#L1903
If
data_encodingisHTTP_ENCODING_LENGTHthen a remaining size of 0 means there is no data at all so the state shouldn't stay asRECV.Temporary workaround
The issue can be bypassed by calling
httpPeek()after finishing the read loop:While this is convenient as a workaround, this implies an additionnal caveat for the fix. If
httpRead()correctly updates the state then callingwould yield the expected result if the body contains data. But with an empty body, the state would first transition from
POST_RECVtoPOST_SEND, thenHTTP_STATE_STATUSin the call tohttpRead()(all states exceptRECVtransition toSTATUS).