From: Michael Wallner Date: Wed, 24 Aug 2005 13:05:00 +0000 (+0000) Subject: - single LF aware http_chunked_decode() X-Git-Tag: RELEASE_0_12_0~20 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=52affd69e8de1f018146eef6fe5b60d2f1801294;p=m6w6%2Fext-http - single LF aware http_chunked_decode() --- diff --git a/http_api.c b/http_api.c index d0f91c6..8246d59 100644 --- a/http_api.c +++ b/http_api.c @@ -281,29 +281,28 @@ PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_ /* }}} */ /* {{{ char *http_chunked_decode(char *, size_t, char **, size_t *) */ -PHP_HTTP_API const char *_http_chunked_decode(const char *encoded, size_t encoded_len, - char **decoded, size_t *decoded_len TSRMLS_DC) +PHP_HTTP_API const char *_http_chunked_decode(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC) { const char *e_ptr; char *d_ptr; - + *decoded_len = 0; *decoded = ecalloc(1, encoded_len); d_ptr = *decoded; e_ptr = encoded; while (((e_ptr - encoded) - encoded_len) > 0) { - int no_crlf = 0; + size_t chunk_len = 0, EOL_len = 0; + int eol_mismatch = 0; char *n_ptr; - size_t chunk_len = 0; chunk_len = strtol(e_ptr, &n_ptr, 16); /* check if: * - we could not read in chunk size - * - chunk size is not followed by HTTP_CRLF|NUL + * - chunk size is not followed by (CR)LF|NUL */ - if ((n_ptr == e_ptr) || (*n_ptr && (no_crlf = strncmp(n_ptr, HTTP_CRLF, lenof(HTTP_CRLF))))) { + if ((n_ptr == e_ptr) || (*n_ptr && (eol_mismatch = n_ptr != http_locate_eol(e_ptr, &EOL_len)))) { /* don't fail on apperently not encoded data */ if (e_ptr == encoded) { memcpy(*decoded, encoded, encoded_len); @@ -311,10 +310,14 @@ PHP_HTTP_API const char *_http_chunked_decode(const char *encoded, size_t encode return encoded + encoded_len; } else { efree(*decoded); - if (no_crlf) { - http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid character (expected 0x0D 0x0A; got: 0x%x 0x%x)", *n_ptr, *(n_ptr + 1)); + if (eol_mismatch) { + if (EOL_len == 2) { + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid character (expected 0x0D 0x0A; got: 0x%X 0x%X)", *n_ptr, *(n_ptr + 1)); + } else { + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid character (expected 0x0A; got: 0x%X)", *n_ptr); + } } else { - char *error = estrndup(n_ptr, strcspn(n_ptr, "\r\n \0")); + char *error = estrndup(n_ptr, strcspn(n_ptr, "\r\n ")); http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Invalid chunk size: '%s' at pos %d", error, n_ptr - encoded); efree(error); } @@ -330,9 +333,9 @@ PHP_HTTP_API const char *_http_chunked_decode(const char *encoded, size_t encode break; } - memcpy(d_ptr, e_ptr += 2, chunk_len); + memcpy(d_ptr, e_ptr += EOL_len, chunk_len); d_ptr += chunk_len; - e_ptr += chunk_len + 2; + e_ptr += chunk_len + EOL_len; *decoded_len += chunk_len; } diff --git a/php_http_api.h b/php_http_api.h index 8906e2c..25d305c 100644 --- a/php_http_api.h +++ b/php_http_api.h @@ -75,6 +75,17 @@ static inline const char *_http_locate_body(const char *message) } } +#define http_locate_eol _http_locate_eol +static inline const char *_http_locate_eol(const char *line, size_t *eol_len) +{ + const char *eol = strpbrk(line, "\r\n"); + + if (eol_len) { + *eol_len = eol ? ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1) : 0; + } + return eol; +} + #endif /* diff --git a/tests/chunked_decode_001.phpt b/tests/chunked_decode_001.phpt index 27f750b..2575704 100644 --- a/tests/chunked_decode_001.phpt +++ b/tests/chunked_decode_001.phpt @@ -1,5 +1,5 @@ --TEST-- -http_chunked_decode() +http_chunked_decode() "\r\n" --SKIPIF-- --EXPECTF-- %sTEST -string(9) "aba -cabcd" +string(12) "abra +cadabra" diff --git a/tests/chunked_decode_002.phpt b/tests/chunked_decode_002.phpt new file mode 100644 index 0000000..8221ee8 --- /dev/null +++ b/tests/chunked_decode_002.phpt @@ -0,0 +1,25 @@ +--TEST-- +http_chunked_decode() "\n" +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +%sTEST +string(12) "abra +cadabra" +