Bug Fix: Connection:close with missing Content-Length.

The test and bug report are from tomika.
event_stream
Ryan 15 years ago
parent f3214f9764
commit efd801f410

@ -96,7 +96,7 @@ struct http_parser {
unsigned short method; /* requests only */ unsigned short method; /* requests only */
short version; short version;
short keep_alive; short keep_alive;
size_t content_length; ssize_t content_length;
/** PUBLIC **/ /** PUBLIC **/
void *data; /* A pointer to get hook to the "connection" or "socket" object */ void *data; /* A pointer to get hook to the "connection" or "socket" object */

@ -27,9 +27,10 @@
#include <assert.h> #include <assert.h>
/* parser->flags */ /* parser->flags */
#define EATING 0x01 #define EATING 0x01
#define ERROR 0x02 #define ERROR 0x02
#define CHUNKED 0x04 #define CHUNKED 0x04
#define EAT_FOREVER 0x10
static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 static int unhex[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
@ -79,7 +80,7 @@ do { \
parser->method = 0; \ parser->method = 0; \
parser->version = HTTP_VERSION_OTHER; \ parser->version = HTTP_VERSION_OTHER; \
parser->keep_alive = -1; \ parser->keep_alive = -1; \
parser->content_length = 0; \ parser->content_length = -1; \
parser->body_read = 0 parser->body_read = 0
#define END_REQUEST \ #define END_REQUEST \
@ -226,6 +227,7 @@ do { \
} }
action content_length { action content_length {
if (parser->content_length == -1) parser->content_length = 0;
if (parser->content_length > INT_MAX) { if (parser->content_length > INT_MAX) {
parser->flags |= ERROR; parser->flags |= ERROR;
return 0; return 0;
@ -281,11 +283,25 @@ do { \
if (parser->flags & CHUNKED) { if (parser->flags & CHUNKED) {
fnext ChunkedBody; fnext ChunkedBody;
} else { } else {
/* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */ /* this is pretty stupid. i'd prefer to combine this with
parser->chunk_size = parser->content_length; * skip_chunk_data */
if (parser->content_length < 0) {
/* If we didn't get a content length; if not keep-alive
* just read body until EOF */
if (!http_parser_should_keep_alive(parser)) {
parser->flags |= EAT_FOREVER;
parser->chunk_size = REMAINING;
} else {
/* Otherwise, if keep-alive, then assume the message
* has no body. */
parser->chunk_size = parser->content_length = 0;
}
} else {
parser->chunk_size = parser->content_length;
}
p += 1; p += 1;
SKIP_BODY(MIN(REMAINING, parser->content_length)); SKIP_BODY(MIN(REMAINING, parser->chunk_size));
if (callback_return_value != 0) { if (callback_return_value != 0) {
parser->flags |= ERROR; parser->flags |= ERROR;
@ -444,11 +460,27 @@ http_parser_execute (http_parser *parser, const char *buffer, size_t len)
{ {
size_t tmp; // REMOVE ME this is extremely hacky size_t tmp; // REMOVE ME this is extremely hacky
int callback_return_value = 0; int callback_return_value = 0;
const char *p, *pe; const char *p, *pe, *eof;
int cs = parser->cs; int cs = parser->cs;
p = buffer; p = buffer;
pe = buffer+len; pe = buffer+len;
eof = len ? NULL : pe;
if (parser->flags & EAT_FOREVER) {
if (len == 0) {
if (parser->on_message_complete) {
callback_return_value = parser->on_message_complete(parser);
if (callback_return_value != 0) parser->flags |= ERROR;
}
} else {
if (parser->on_body) {
callback_return_value = parser->on_body(parser, p, len);
if (callback_return_value != 0) parser->flags |= ERROR;
}
}
return len;
}
if (0 < parser->chunk_size && (parser->flags & EATING)) { if (0 < parser->chunk_size && (parser->flags & EATING)) {
/* eat body */ /* eat body */

@ -344,6 +344,45 @@ const struct message responses[] =
"</BODY></HTML>\r\n" "</BODY></HTML>\r\n"
} }
, {.name= "no content-length response"
,.type= HTTP_RESPONSE
,.raw= "HTTP/1.1 200 OK\r\n"
"Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n"
"Server: Apache\r\n"
"X-Powered-By: Servlet/2.5 JSP/2.1\r\n"
"Content-Type: text/xml; charset=utf-8\r\n"
"Connection: close\r\n"
"\r\n"
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
" <SOAP-ENV:Body>\n"
" <SOAP-ENV:Fault>\n"
" <faultcode>SOAP-ENV:Client</faultcode>\n"
" <faultstring>Client Error</faultstring>\n"
" </SOAP-ENV:Fault>\n"
" </SOAP-ENV:Body>\n"
"</SOAP-ENV:Envelope>"
,.should_keep_alive= FALSE
,.status_code= 200
,.num_headers= 5
,.headers=
{ { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }
, { "Server", "Apache" }
, { "X-Powered-By", "Servlet/2.5 JSP/2.1" }
, { "Content-Type", "text/xml; charset=utf-8" }
, { "Connection", "close" }
}
,.body= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
" <SOAP-ENV:Body>\n"
" <SOAP-ENV:Fault>\n"
" <faultcode>SOAP-ENV:Client</faultcode>\n"
" <faultstring>Client Error</faultstring>\n"
" </SOAP-ENV:Fault>\n"
" </SOAP-ENV:Body>\n"
"</SOAP-ENV:Envelope>"
}
, {.name= "404 no headers no body" , {.name= "404 no headers no body"
,.type= HTTP_RESPONSE ,.type= HTTP_RESPONSE
,.raw= "HTTP/1.1 404 Not Found\r\n\r\n" ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"

Loading…
Cancel
Save