Skip to content
This repository has been archived by the owner on Nov 6, 2022. It is now read-only.

Fix http_parser_parse_url to handle very long URLs #480

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
HELPER ?=
BINEXT ?=
SOLIBNAME = libhttp_parser
SOMAJOR = 2
SOMINOR = 9
SOREV = 2
SOMAJOR = 3
SOMINOR = 0
SOREV = 0
ifeq (darwin,$(PLATFORM))
SOEXT ?= dylib
SONAME ?= $(SOLIBNAME).$(SOMAJOR).$(SOMINOR).$(SOEXT)
Expand Down
14 changes: 7 additions & 7 deletions http_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2278,14 +2278,14 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
switch(new_s) {
case s_http_host:
if (s != s_http_host) {
u->field_data[UF_HOST].off = (uint16_t)(p - buf);
u->field_data[UF_HOST].off = (size_t)(p - buf);
}
u->field_data[UF_HOST].len++;
break;

case s_http_host_v6:
if (s != s_http_host_v6) {
u->field_data[UF_HOST].off = (uint16_t)(p - buf);
u->field_data[UF_HOST].off = (size_t)(p - buf);
}
u->field_data[UF_HOST].len++;
break;
Expand All @@ -2297,7 +2297,7 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {

case s_http_host_port:
if (s != s_http_host_port) {
u->field_data[UF_PORT].off = (uint16_t)(p - buf);
u->field_data[UF_PORT].off = (size_t)(p - buf);
u->field_data[UF_PORT].len = 0;
u->field_set |= (1 << UF_PORT);
}
Expand All @@ -2306,7 +2306,7 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {

case s_http_userinfo:
if (s != s_http_userinfo) {
u->field_data[UF_USERINFO].off = (uint16_t)(p - buf);
u->field_data[UF_USERINFO].off = (size_t)(p - buf);
u->field_data[UF_USERINFO].len = 0;
u->field_set |= (1 << UF_USERINFO);
}
Expand Down Expand Up @@ -2410,7 +2410,7 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
continue;
}

u->field_data[uf].off = (uint16_t)(p - buf);
u->field_data[uf].off = (size_t)(p - buf);
u->field_data[uf].len = 1;

u->field_set |= (1 << uf);
Expand All @@ -2436,8 +2436,8 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
}

if (u->field_set & (1 << UF_PORT)) {
uint16_t off;
uint16_t len;
size_t off;
size_t len;
const char* p;
const char* end;
unsigned long v;
Expand Down
10 changes: 5 additions & 5 deletions http_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ extern "C" {
#endif

/* Also update SONAME in the Makefile whenever you change these. */
#define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 9
#define HTTP_PARSER_VERSION_PATCH 2
#define HTTP_PARSER_VERSION_MAJOR 3
#define HTTP_PARSER_VERSION_MINOR 0
#define HTTP_PARSER_VERSION_PATCH 0

#include <stddef.h>
#if defined(_WIN32) && !defined(__MINGW32__) && \
Expand Down Expand Up @@ -362,8 +362,8 @@ struct http_parser_url {
uint16_t port; /* Converted UF_PORT string */

struct {
uint16_t off; /* Offset into buffer in which field starts */
uint16_t len; /* Length of run in buffer */
size_t off; /* Offset into buffer in which field starts */
size_t len; /* Length of run in buffer */
} field_data[UF_MAX];
};

Expand Down
29 changes: 26 additions & 3 deletions test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2554,7 +2554,7 @@ check_num_eq (const struct message *m,

#define MESSAGE_CHECK_URL_EQ(u, expected, found, prop, fn) \
do { \
char ubuf[256]; \
char ubuf[65537+1]; \
\
if ((u)->field_set & (1 << (fn))) { \
memcpy(ubuf, (found)->request_url + (u)->field_data[(fn)].off, \
Expand Down Expand Up @@ -3337,6 +3337,29 @@ const struct url_test url_tests[] =
,.rv=0
}
#endif
#define REP32(X) X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
#define REP256(X) REP32(X) REP32(X) REP32(X) REP32(X) REP32(X) REP32(X) REP32(X) REP32(X)
#define REP2048(X) REP256(X) REP256(X) REP256(X) REP256(X) REP256(X) REP256(X) REP256(X) REP256(X)
#define REP16384(X) REP2048(X) REP2048(X) REP2048(X) REP2048(X) REP2048(X) REP2048(X) REP2048(X) REP2048(X)
#define REP65536(X) REP16384(X) REP16384(X) REP16384(X) REP16384(X)
, {.name="very long path and query"
,.url="http://hostname/" REP65536("A") "?" REP65536("B")
,.is_connect=0
,.u=
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) | (1 << UF_QUERY)
,.port=0
,.field_data=
{{ 0, 4 } /* UF_SCHEMA */
,{ 7, 8 } /* UF_HOST */
,{ 0, 0 } /* UF_PORT */
,{ 15, 65537 } /* UF_PATH */
,{ 65553, 65536 } /* UF_QUERY */
,{ 0, 0 } /* UF_FRAGMENT */
,{ 0, 0 } /* UF_USERINFO */
}
}
,.rv=0
}
};

void
Expand All @@ -3351,11 +3374,11 @@ dump_url (const char *url, const struct http_parser_url *u)
continue;
}

printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"",
printf("\tfield_data[%u]: off: %zu len: %zu part: \"%.*s\"\n",
i,
u->field_data[i].off,
u->field_data[i].len,
u->field_data[i].len,
(int)u->field_data[i].len,
url + u->field_data[i].off);
}
}
Expand Down