return 0;
}
+PHP_HTTP_BUFFER_API char *php_http_buffer_account(php_http_buffer_t *buf, size_t to_account)
+{
+ /* it's probably already too late but check anyway */
+ if (to_account > buf->free) {
+ return NULL;
+ }
+
+ buf->free -= to_account;
+ buf->used += to_account;
+
+ return buf->data + buf->used;
+}
+
PHP_HTTP_BUFFER_API size_t php_http_buffer_shrink(php_http_buffer_t *buf)
{
/* avoid another realloc on fixation */
#define php_http_buffer_resize(b, s) php_http_buffer_resize_ex((b), (s), 0, 0)
PHP_HTTP_BUFFER_API size_t php_http_buffer_resize_ex(php_http_buffer_t *buf, size_t len, size_t override_size, int allow_error);
+PHP_HTTP_BUFFER_API char *php_http_buffer_account(php_http_buffer_t *buf, size_t to_account);
+
/* shrink memory chunk to actually used size (+1) */
PHP_HTTP_BUFFER_API size_t php_http_buffer_shrink(php_http_buffer_t *buf);
fprintf(stderr, "\n%3d: %3d PRIOR: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
#endif
status = inflate(Z, flush);
-
- buffer.used += buffer.free - Z->avail_out;
- buffer.free = Z->avail_out;
+ php_http_buffer_account(&buffer, buffer.free - Z->avail_out);
#if 0
fprintf(stderr, "%3d: %3d AFTER: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
#endif
status = inflateInit2(&Z, wbits);
if (Z_OK == status) {
Z.next_in = (Bytef *) data;
- Z.avail_in = data_len;
+ Z.avail_in = data_len + 1; /* include the terminating NULL, see #61287 */
switch (status = php_http_inflate_rounds(&Z, Z_NO_FLUSH, decoded, decoded_len)) {
case Z_STREAM_END:
case PHP_HTTP_MESSAGE_PARSER_STATE_HEADER:
case PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE:
/* read line */
- php_stream_get_line(s, buf.data, buf.free, &len);
- buf.used += len;
- buf.free -= len;
+ php_stream_get_line(s, buf.data + buf.used, buf.free, &len);
+ php_http_buffer_account(&buf, len);
break;
case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB:
/* read all */
- len = php_stream_read(s, buf.data, buf.free);
- buf.used += len;
- buf.free -= len;
+ php_http_buffer_account(&buf, php_stream_read(s, buf.data + buf.used, buf.free));
break;
case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH:
/* read body_length */
- len = php_stream_read(s, buf.data, MIN(buf.free, parser->body_length));
- buf.used += len;
- buf.free -= len;
+ php_http_buffer_account(&buf, php_stream_read(s, buf.data + buf.used, MIN(buf.free, parser->body_length)));
break;
case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED:
/* duh, this is very naive */
if (len) {
- size_t read = php_stream_read(s, buf.data, MIN(len, buf.free));
+ size_t read = php_stream_read(s, buf.data + buf.used, MIN(len, buf.free));
- buf.used += read;
- buf.free -= read;
+ php_http_buffer_account(&buf, read);
len -= read;
} else {
php_stream_get_line(s, buf.data, buf.free, &len);
- buf.used += len;
- buf.free -= len;
+ php_http_buffer_account(&buf, len);
len = strtoul(buf.data - len, NULL, 16);
}