src: fix out-of-bounds read through `strtoul`

`strtoul` will attempt to lookup the next digit up until it will stumble
upon an invalid one. However, for an unterminated string as an input
value, this results in out-of-bounds read.

Remove `strtoul` call, and replace it with simple loop.

Fix: #408
PR-URL: https://github.com/nodejs/http-parser/pull/409
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
make-http-max-header-size-gyp-configurable
Fedor Indutny 7 years ago
parent b11de0f5c6
commit 9ce7316de3

@ -22,7 +22,6 @@
#include <assert.h> #include <assert.h>
#include <stddef.h> #include <stddef.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
@ -2367,12 +2366,27 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
} }
if (u->field_set & (1 << UF_PORT)) { if (u->field_set & (1 << UF_PORT)) {
/* Don't bother with endp; we've already validated the string */ uint16_t off;
unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10); uint16_t len;
const char* p;
/* Ports have a max value of 2^16 */ const char* end;
if (v > 0xffff) { unsigned long v;
return 1;
off = u->field_data[UF_PORT].off;
len = u->field_data[UF_PORT].len;
end = buf + off + len;
/* NOTE: The characters are already validated and are in the [0-9] range */
assert(off + len <= buflen && "Port number overflow");
v = 0;
for (p = buf + off; p < end; p++) {
v *= 10;
v += *p - '0';
/* Ports have a max value of 2^16 */
if (v > 0xffff) {
return 1;
}
} }
u->port = (uint16_t) v; u->port = (uint16_t) v;

@ -3664,6 +3664,30 @@ test_header_cr_no_lf_error (int req)
abort(); abort();
} }
void
test_no_overflow_parse_url (void)
{
int rv;
struct http_parser_url u;
http_parser_url_init(&u);
rv = http_parser_parse_url("http://example.com:8001", 22, 0, &u);
if (rv != 0) {
fprintf(stderr,
"\n*** test_no_overflow_parse_url invalid return value=%d\n",
rv);
abort();
}
if (u.port != 800) {
fprintf(stderr,
"\n*** test_no_overflow_parse_url invalid port number=%d\n",
u.port);
abort();
}
}
void void
test_header_overflow_error (int req) test_header_overflow_error (int req)
{ {
@ -4099,6 +4123,7 @@ main (void)
test_header_nread_value(); test_header_nread_value();
//// OVERFLOW CONDITIONS //// OVERFLOW CONDITIONS
test_no_overflow_parse_url();
test_header_overflow_error(HTTP_REQUEST); test_header_overflow_error(HTTP_REQUEST);
test_no_overflow_long_body(HTTP_REQUEST, 1000); test_no_overflow_long_body(HTTP_REQUEST, 1000);

Loading…
Cancel
Save