Compare commits

...

2 Commits

Author SHA1 Message Date
bca7167d03 Fix the SCGI parser and tests 2018-10-18 06:34:16 +02:00
3e4e4e5103 Allow aborting the FastCGI protocol parser 2018-10-18 04:08:47 +02:00
3 changed files with 36 additions and 16 deletions

View File

@@ -664,10 +664,11 @@ scgi_parser_push (struct scgi_parser *self,
if (digit == ':')
{
self->state = SCGI_READING_NAME;
str_remove_slice (&self->input, 0, 1);
break;
}
if (digit < '0' || digit >= '9')
if (digit < '0' || digit > '9')
return error_set (e, "invalid header netstring");
size_t new_len = self->headers_len * 10 + (digit - '0');
@@ -700,6 +701,7 @@ scgi_parser_push (struct scgi_parser *self,
self->state = SCGI_READING_VALUE;
str_remove_slice (&self->input, 0, 1);
self->headers_len--;
break;
}
case SCGI_READING_VALUE:
@@ -728,6 +730,7 @@ scgi_parser_push (struct scgi_parser *self,
}
str_remove_slice (&self->input, 0, 1);
self->headers_len--;
break;
}
case SCGI_READING_CONTENT:
@@ -792,7 +795,8 @@ enum fcgi_protocol_status
struct fcgi_parser;
typedef void (*fcgi_message_fn)
/// Message handler, returns false if further processing should be stopped
typedef bool (*fcgi_message_fn)
(const struct fcgi_parser *parser, void *user_data);
enum fcgi_parser_state
@@ -854,7 +858,7 @@ fcgi_parser_unpack_header (struct fcgi_parser *self)
str_remove_slice (&self->input, 0, unpacker.offset);
}
static void
static bool
fcgi_parser_push (struct fcgi_parser *self, const void *data, size_t len)
{
// This could be made considerably faster for high-throughput applications
@@ -866,14 +870,14 @@ fcgi_parser_push (struct fcgi_parser *self, const void *data, size_t len)
{
case FCGI_READING_HEADER:
if (self->input.len < FCGI_HEADER_LEN)
return;
return true;
fcgi_parser_unpack_header (self);
self->state = FCGI_READING_CONTENT;
break;
case FCGI_READING_CONTENT:
if (self->input.len < self->content_length)
return;
return true;
// Move an appropriate part of the input buffer to the content buffer
str_reset (&self->content);
@@ -883,10 +887,11 @@ fcgi_parser_push (struct fcgi_parser *self, const void *data, size_t len)
break;
case FCGI_READING_PADDING:
if (self->input.len < self->padding_length)
return;
return true;
// Call the callback to further process the message
self->on_message (self, self->user_data);
if (!self->on_message (self, self->user_data))
return false;
// Remove the padding from the input buffer
str_remove_slice (&self->input, 0, self->padding_length);

View File

@@ -1093,7 +1093,7 @@ struct async
LIST_HEADER (struct async)
struct async_manager *manager; ///< Our manager object
// "cancelled" may not be accesed or modified by the worker thread
// "cancelled" may not be accessed or modified by the worker thread
pthread_t worker; ///< Worker thread ID
bool started; ///< Worker thread ID is valid

View File

@@ -105,10 +105,20 @@ test_http_parser (void)
http_protocol_destroy (iter);
}
struct scgi_fixture
{
struct scgi_parser parser;
bool seen_headers;
bool seen_content;
};
static bool
test_scgi_parser_on_headers_read (void *user_data)
{
struct scgi_parser *parser = user_data;
struct scgi_fixture *fixture = user_data;
struct scgi_parser *parser = &fixture->parser;
fixture->seen_headers = true;
soft_assert (parser->headers.len == 4);
soft_assert (!strcmp (str_map_find (&parser->headers,
"CONTENT_LENGTH"), "27"));
@@ -124,7 +134,9 @@ test_scgi_parser_on_headers_read (void *user_data)
static bool
test_scgi_parser_on_content (void *user_data, const void *data, size_t len)
{
(void) user_data;
struct scgi_fixture *fixture = user_data;
fixture->seen_content = true;
soft_assert (!strncmp (data, "What is the answer to life?", len));
return true;
}
@@ -132,10 +144,12 @@ test_scgi_parser_on_content (void *user_data, const void *data, size_t len)
static void
test_scgi_parser (void)
{
struct scgi_parser parser = scgi_parser_make ();
parser.on_headers_read = test_scgi_parser_on_headers_read;
parser.on_content = test_scgi_parser_on_content;
parser.user_data = &parser;
struct scgi_fixture fixture = { scgi_parser_make(), false, false };
struct scgi_parser *parser = &fixture.parser;
parser->on_headers_read = test_scgi_parser_on_headers_read;
parser->on_content = test_scgi_parser_on_content;
parser->user_data = &fixture;
// This is an example straight from the specification
const char example[] =
@@ -147,8 +161,9 @@ test_scgi_parser (void)
","
"What is the answer to life?";
soft_assert (scgi_parser_push (&parser, example, sizeof example, NULL));
scgi_parser_free (&parser);
soft_assert (scgi_parser_push (parser, example, sizeof example, NULL));
soft_assert (fixture.seen_headers && fixture.seen_content);
scgi_parser_free (parser);
}
static bool