]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: message parser: Don't allocate a pool for the next message until it is...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 4 Feb 2017 12:59:10 +0000 (13:59 +0100)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 17 Feb 2017 09:32:32 +0000 (11:32 +0200)
This prevents wasting memory when no message is being parsed.

src/lib-http/http-message-parser.c
src/lib-http/http-message-parser.h
src/lib-http/http-request-parser.c
src/lib-http/http-response-parser.c

index 3b4cb041dbf3b0521facacd7749ee15420b2482c..c6271bb8cc1a77854f9bee2fda20e8196ea0884d 100644 (file)
@@ -54,15 +54,20 @@ void http_message_parser_restart(struct http_message_parser *parser,
        if (parser->msg.pool != NULL)
                pool_unref(&parser->msg.pool);
        i_zero(&parser->msg);
-       if (pool == NULL) {
-               parser->msg.pool = pool_alloconly_create("http_message", 4096);
-       } else {
+       if (pool != NULL) {
                parser->msg.pool = pool;
                pool_ref(pool);
        }
        parser->msg.date = (time_t)-1;
 }
 
+pool_t http_message_parser_get_pool(struct http_message_parser *parser)
+{
+       if (parser->msg.pool == NULL)
+               parser->msg.pool = pool_alloconly_create("http_message", 4096);
+       return parser->msg.pool;
+}
+
 int http_message_parse_version(struct http_message_parser *parser)
 {
        const unsigned char *p = parser->cur;
@@ -130,9 +135,11 @@ http_message_parse_header(struct http_message_parser *parser,
 {
        const struct http_header_field *hdr;
        struct http_parser hparser;
+       pool_t pool;
 
+       pool = http_message_parser_get_pool(parser);
        if (parser->msg.header == NULL)
-               parser->msg.header = http_header_create(parser->msg.pool, 32);
+               parser->msg.header = http_header_create(pool, 32);
        hdr = http_header_field_add(parser->msg.header, name, data, size);
 
        /* RFC 7230, Section 3.2.2: Field Order
@@ -166,9 +173,9 @@ http_message_parse_header(struct http_message_parser *parser,
                                if (strcasecmp(option, "close") == 0)
                                        parser->msg.connection_close = TRUE;
                                if (!array_is_created(&parser->msg.connection_options))
-                                       p_array_init(&parser->msg.connection_options, parser->msg.pool, 4);
+                                       p_array_init(&parser->msg.connection_options, pool, 4);
                                opt_idx = array_append_space(&parser->msg.connection_options);
-                               *opt_idx = p_strdup(parser->msg.pool, option);
+                               *opt_idx = p_strdup(pool, option);
                        }
 
                        if (hparser.cur < hparser.end || num_tokens == 0) {
@@ -238,7 +245,7 @@ http_message_parse_header(struct http_message_parser *parser,
        
                        /* Multiple Transfer-Encoding headers are allowed and combined into one */
                        if (!array_is_created(&parser->msg.transfer_encoding))
-                               p_array_init(&parser->msg.transfer_encoding, parser->msg.pool, 4);
+                               p_array_init(&parser->msg.transfer_encoding, pool, 4);
 
                        /* RFC 7230, Section 3.3.1: Transfer-Encoding
 
@@ -262,7 +269,7 @@ http_message_parse_header(struct http_message_parser *parser,
                                        bool parse_error;
 
                                        coding = array_append_space(&parser->msg.transfer_encoding);
-                                       coding->name = p_strdup(parser->msg.pool, trenc);
+                                       coding->name = p_strdup(pool, trenc);
                
                                        /* *( OWS ";" OWS transfer-parameter ) */
                                        parse_error = FALSE;
@@ -299,10 +306,10 @@ http_message_parse_header(struct http_message_parser *parser,
                                                }
                
                                                if (!array_is_created(&coding->parameters))
-                                                       p_array_init(&coding->parameters, parser->msg.pool, 2);
+                                                       p_array_init(&coding->parameters, pool, 2);
                                                param = array_append_space(&coding->parameters);
-                                               param->attribute = p_strdup(parser->msg.pool, attribute);
-                                               param->value = p_strdup(parser->msg.pool, value);
+                                               param->attribute = p_strdup(pool, attribute);
+                                               param->value = p_strdup(pool, value);
                                        }
                                        if (parse_error)
                                                break;
@@ -355,11 +362,13 @@ int http_message_parse_headers(struct http_message_parser *parser)
        while ((ret=http_header_parse_next_field(parser->header_parser,
                &field_name, &field_data, &field_size, &error)) > 0) {
                if (field_name == NULL) {
+                       pool_t pool;
                        /* EOH */
 
                        /* Create empty header if there is none */
+                       pool = http_message_parser_get_pool(parser);
                        if (parser->msg.header == NULL)
-                               parser->msg.header = http_header_create(parser->msg.pool, 1);
+                               parser->msg.header = http_header_create(pool, 1);
 
                        /* handle HTTP/1.0 persistence */
                        if (msg->version_major == 1 && msg->version_minor == 0 &&
index f9b39ef41479b82e88b7cbc9f3545d4775b74bfa..7cef0ba743b3b14185f0d6d790e1e23270df9b1d 100644 (file)
@@ -62,6 +62,8 @@ void http_message_parser_deinit(struct http_message_parser *parser);
 void http_message_parser_restart(struct http_message_parser *parser,
        pool_t pool);
 
+pool_t http_message_parser_get_pool(struct http_message_parser *parser);
+
 int http_message_parse_finish_payload(struct http_message_parser *parser);
 int http_message_parse_version(struct http_message_parser *parser);
 int http_message_parse_headers(struct http_message_parser *parser);
index 748fe560a8ecb9369cc7478bd83806eba57887cd..95e9371cb43b16ee0a3ddfe4fd5f1b32879cd072 100644 (file)
@@ -92,6 +92,7 @@ http_request_parser_restart(struct http_request_parser *parser,
 static int http_request_parse_method(struct http_request_parser *parser)
 {
        const unsigned char *p = parser->parser.cur;
+       pool_t pool;
 
        /* method         = token
         */
@@ -105,8 +106,9 @@ static int http_request_parse_method(struct http_request_parser *parser)
        }
        if (p == parser->parser.end)
                return 0;
+       pool = http_message_parser_get_pool(&parser->parser);
        parser->request_method =
-               p_strdup_until(parser->parser.msg.pool, parser->parser.cur, p);
+               p_strdup_until(pool, parser->parser.cur, p);
        parser->parser.cur = p;
        return 1;
 }
@@ -115,6 +117,7 @@ static int http_request_parse_target(struct http_request_parser *parser)
 {
        struct http_message_parser *_parser = &parser->parser;
        const unsigned char *p = parser->parser.cur;
+       pool_t pool;
 
        /* We'll just parse anything up to the first SP or a control char.
           We could also implement workarounds for buggy HTTP clients and
@@ -138,7 +141,8 @@ static int http_request_parse_target(struct http_request_parser *parser)
        }
        if (p == _parser->end)
                return 0;
-       parser->request_target = p_strdup_until(_parser->msg.pool, _parser->cur, p);
+       pool = http_message_parser_get_pool(_parser);
+       parser->request_target = p_strdup_until(pool, _parser->cur, p);
        parser->parser.cur = p;
        return 1;
 }
@@ -574,8 +578,9 @@ int http_request_parse_next(struct http_request_parser *parser,
 
        i_zero(request);
 
+       pool = http_message_parser_get_pool(&parser->parser);
        if (http_url_request_target_parse(parser->request_target, hdr->value,
-               parser->parser.msg.pool, &request->target, &error) < 0) {
+               pool, &request->target, &error) < 0) {
                *error_code_r = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST;
                *error_r = t_strdup_printf("Bad request target `%s': %s",
                        parser->request_target, error);
index a2525c2aaeb8455204230269f8cc11d84d36a8d5..300bcf466e40a19321fc2d44b998b1ad3cb4e707 100644 (file)
@@ -83,6 +83,7 @@ static int http_response_parse_status(struct http_response_parser *parser)
 static int http_response_parse_reason(struct http_response_parser *parser)
 {
        const unsigned char *p = parser->parser.cur;
+       pool_t pool;
 
        /* reason-phrase = *( HTAB / SP / VCHAR / obs-text )
         */
@@ -92,8 +93,9 @@ static int http_response_parse_reason(struct http_response_parser *parser)
 
        if (p == parser->parser.end)
                return 0;
+       pool = http_message_parser_get_pool(&parser->parser);
        parser->response_reason =
-               p_strdup_until(parser->parser.msg.pool, parser->parser.cur, p);
+               p_strdup_until(pool, parser->parser.cur, p);
        parser->parser.cur = p;
        return 1;
 }