diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2002-06-17 19:15:50 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2002-06-17 19:15:50 +0000 |
commit | d27320aa6ec1696185c414c78ff94550b5126a50 (patch) | |
tree | aca4ce21dd3aeddf018119a66b66201b1bda937b | |
parent | 9194de5fc9fdebaa2b7c255608e8c7b89750cd2c (diff) |
The Real Fix for the buffer overflow; from apache.org
ok beck@
-rw-r--r-- | usr.sbin/httpd/src/main/http_protocol.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/usr.sbin/httpd/src/main/http_protocol.c b/usr.sbin/httpd/src/main/http_protocol.c index f86be0d4e06..b373c76ea83 100644 --- a/usr.sbin/httpd/src/main/http_protocol.c +++ b/usr.sbin/httpd/src/main/http_protocol.c @@ -2028,21 +2028,34 @@ API_EXPORT(int) ap_should_client_block(request_rec *r) static long get_chunk_size(char *b) { long chunksize = 0; + long chunkbits = sizeof(long) * 8; - while (ap_isxdigit(*b)) { + /* Skip leading zeros */ + while (*b == '0') { + ++b; + } + + while (ap_isxdigit(*b) && (chunkbits > 0)) { int xvalue = 0; - /* This works even on EBCDIC. */ - if (*b >= '0' && *b <= '9') + if (*b >= '0' && *b <= '9') { xvalue = *b - '0'; - else if (*b >= 'A' && *b <= 'F') + } + else if (*b >= 'A' && *b <= 'F') { xvalue = *b - 'A' + 0xa; - else if (*b >= 'a' && *b <= 'f') + } + else if (*b >= 'a' && *b <= 'f') { xvalue = *b - 'a' + 0xa; + } chunksize = (chunksize << 4) | xvalue; + chunkbits -= 4; ++b; } + if (ap_isxdigit(*b) && (chunkbits <= 0)) { + /* overflow */ + return -1; + } return chunksize; } @@ -2068,7 +2081,7 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz) unsigned long max_body; if (!r->read_chunked) { /* Content-length read */ - len_to_read = (r->remaining > (unsigned int)bufsiz) ? bufsiz : r->remaining; + len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining; len_read = ap_bread(r->connection->client, buffer, len_to_read); if (len_read <= 0) { if (len_read < 0) @@ -2127,6 +2140,10 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz) } r->remaining = -1; /* Indicate footers in-progress */ } + else if (len_to_read < 0) { + r->connection->keepalive = -1; + return -1; + } else { r->remaining = len_to_read; } @@ -2180,7 +2197,7 @@ API_EXPORT(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz) /* Otherwise, we are in the midst of reading a chunk of data */ - len_to_read = (r->remaining > (unsigned int)bufsiz) ? bufsiz : r->remaining; + len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining; len_read = ap_bread(r->connection->client, buffer, len_to_read); if (len_read <= 0) { |