From 31092c29dba06404d2f0d856d5a89f0b28be6f0b Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 19 Apr 2006 15:42:28 +0000 Subject: [PATCH] - force syncronized flush on encoding stream - allow erealloc failure in phpstr_resize_ex() # appending a *deflate* (zlib/gzip) filter to a stream # for reading won't make one happy, though --- http_encoding_api.c | 12 ++++++------ http_filter_api.c | 42 ++++++++++++++++++++++++++--------------- php_http_encoding_api.h | 9 +++++++++ phpstr/phpstr.c | 12 +++++++++--- phpstr/phpstr.h | 4 ++-- 5 files changed, 53 insertions(+), 26 deletions(-) diff --git a/http_encoding_api.c b/http_encoding_api.c index f732d43..bf6fd5c 100644 --- a/http_encoding_api.c +++ b/http_encoding_api.c @@ -343,9 +343,9 @@ retry_inflate: Z.avail_in = data_len; do { - phpstr_resize(&buffer, data_len << 2); - - do { + if (phpstr_resize_ex(&buffer, data_len << 2, 0, 1) == (size_t) -1) { + status = Z_MEM_ERROR; + } else do { Z.avail_out = (buffer.free -= Z.total_out - buffer.used); Z.next_out = (Bytef *) buffer.data + (buffer.used = Z.total_out); status = inflate(&Z, Z_NO_FLUSH); @@ -457,7 +457,7 @@ PHP_HTTP_API STATUS _http_encoding_deflate_stream_update(http_encoding_stream *s s->stream.avail_out = *encoded_len; s->stream.next_out = (Bytef *) *encoded; - switch (status = deflate(&s->stream, Z_NO_FLUSH)) + switch (status = deflate(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags))) { case Z_OK: case Z_STREAM_END: @@ -503,7 +503,7 @@ retry_raw_inflate: s->stream.next_out = (Bytef *) *decoded; s->stream.avail_out = *decoded_len; - switch (status = inflate(&s->stream, Z_NO_FLUSH)) + switch (status = inflate(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags))) { case Z_OK: case Z_STREAM_END: @@ -549,7 +549,7 @@ PHP_HTTP_API STATUS _http_encoding_deflate_stream_flush(http_encoding_stream *s, s->stream.avail_out = *encoded_len; s->stream.next_out = (Bytef *) *encoded; - switch (status = deflate(&s->stream, Z_SYNC_FLUSH)) + switch (status = deflate(&s->stream, Z_FULL_FLUSH)) { case Z_OK: case Z_STREAM_END: diff --git a/http_filter_api.c b/http_filter_api.c index 02467de..8d138b9 100644 --- a/http_filter_api.c +++ b/http_filter_api.c @@ -313,8 +313,10 @@ static HTTP_FILTER_FUNCTION(deflate) if (ptr->buflen) { http_encoding_deflate_stream_update(buffer, ptr->buf, ptr->buflen, &encoded, &encoded_len); if (encoded) { - out_avail = 1; - NEW_BUCKET(encoded, encoded_len); + if (encoded_len) { + out_avail = 1; + NEW_BUCKET(encoded, encoded_len); + } efree(encoded); } } @@ -331,8 +333,10 @@ static HTTP_FILTER_FUNCTION(deflate) http_encoding_deflate_stream_flush(buffer, &encoded, &encoded_len); if (encoded) { - out_avail = 1; - NEW_BUCKET(encoded, encoded_len); + if (encoded_len) { + out_avail = 1; + NEW_BUCKET(encoded, encoded_len); + } efree(encoded); } } @@ -343,8 +347,10 @@ static HTTP_FILTER_FUNCTION(deflate) http_encoding_deflate_stream_finish(buffer, &encoded, &encoded_len); if (encoded) { - out_avail = 1; - NEW_BUCKET(encoded, encoded_len); + if (encoded_len) { + out_avail = 1; + NEW_BUCKET(encoded, encoded_len); + } efree(encoded); } } @@ -378,8 +384,10 @@ static HTTP_FILTER_FUNCTION(inflate) if (ptr->buflen) { http_encoding_inflate_stream_update(buffer, ptr->buf, ptr->buflen, &decoded, &decoded_len); if (decoded) { - out_avail = 1; - NEW_BUCKET(decoded, decoded_len); + if (decoded_len) { + out_avail = 1; + NEW_BUCKET(decoded, decoded_len); + } efree(decoded); } } @@ -396,8 +404,10 @@ static HTTP_FILTER_FUNCTION(inflate) http_encoding_inflate_stream_flush(buffer, &decoded, &decoded_len); if (decoded) { - out_avail = 1; - NEW_BUCKET(decoded, decoded_len); + if (decoded_len) { + out_avail = 1; + NEW_BUCKET(decoded, decoded_len); + } efree(decoded); } } @@ -408,8 +418,10 @@ static HTTP_FILTER_FUNCTION(inflate) http_encoding_inflate_stream_finish(buffer, &decoded, &decoded_len); if (decoded) { - out_avail = 1; - NEW_BUCKET(decoded, decoded_len); + if (decoded_len) { + out_avail = 1; + NEW_BUCKET(decoded, decoded_len); + } efree(decoded); } } @@ -465,7 +477,7 @@ static php_stream_filter *http_filter_create(const char *name, zval *params, int } else if (!strcasecmp(name, "http.inflate")) { - int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0; + int flags = HTTP_ENCODING_STREAM_FLUSH_SYNC | (p ? HTTP_ENCODING_STREAM_PERSISTENT : 0); HTTP_FILTER_BUFFER(inflate) *b = NULL; if ((b = http_encoding_inflate_stream_init(NULL, flags))) { @@ -476,7 +488,7 @@ static php_stream_filter *http_filter_create(const char *name, zval *params, int } else if (!strcasecmp(name, "http.deflate")) { - int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0; + int flags = HTTP_ENCODING_STREAM_FLUSH_SYNC | (p ? HTTP_ENCODING_STREAM_PERSISTENT : 0); HTTP_FILTER_BUFFER(deflate) *b = NULL; if (params) { @@ -492,7 +504,7 @@ static php_stream_filter *http_filter_create(const char *name, zval *params, int zval *orig = *tmp; convert_to_long_ex(tmp); - flags |= (Z_LVAL_PP(tmp) & 0x0fffffff); + flags |= (Z_LVAL_PP(tmp) & 0x00ffffff); if (orig != *tmp) zval_ptr_dtor(tmp); } } diff --git a/php_http_encoding_api.h b/php_http_encoding_api.h index 8854033..88b4295 100644 --- a/php_http_encoding_api.h +++ b/php_http_encoding_api.h @@ -62,6 +62,15 @@ typedef enum _http_encoding_type_t { #define HTTP_INFLATE_TYPE_GZIP 0x00000000 #define HTTP_INFLATE_TYPE_RAW 0x00000001 +#define HTTP_ENCODING_STREAM_FLUSH_NONE 0x00000000 +#define HTTP_ENCODING_STREAM_FLUSH_SYNC 0x00100000 +#define HTTP_ENCODING_STREAM_FLUSH_FULL 0x00200000 + +#define HTTP_ENCODING_STREAM_FLUSH_FLAG(f) ( \ + (f) & HTTP_ENCODING_STREAM_FLUSH_FULL ? Z_FULL_FLUSH : \ + (f) & HTTP_ENCODING_STREAM_FLUSH_SYNC ? Z_SYNC_FLUSH : \ + Z_NO_FLUSH) + #define HTTP_ENCODING_STREAM_PERSISTENT 0x01000000 typedef struct _http_encoding_stream_t { diff --git a/phpstr/phpstr.c b/phpstr/phpstr.c index a312b1e..4eaec1c 100644 --- a/phpstr/phpstr.c +++ b/phpstr/phpstr.c @@ -34,7 +34,7 @@ PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t return buf; } -PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size) +PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error) { #if 0 fprintf(stderr, "RESIZE: size=%lu, used=%lu, free=%lu\n", buf->size, buf->used, buf->free); @@ -46,7 +46,13 @@ PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size size *= 2; } if (buf->data) { - char *ptr = perealloc(buf->data, buf->used + buf->free + size, buf->pmem); + char *ptr; + + if (allow_error) { + ptr = perealloc_recoverable(buf->data, buf->used + buf->free + size, buf->pmem); + } else { + ptr = perealloc(buf->data, buf->used + buf->free + size, buf->pmem); + } if (ptr) { buf->data = ptr; @@ -279,7 +285,7 @@ PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...) PHPSTR_API phpstr *phpstr_fix(phpstr *buf) { - if (NOMEM == phpstr_resize_ex(buf, 1, 1)) { + if (NOMEM == phpstr_resize_ex(buf, 1, 1, 0)) { return NULL; } buf->data[buf->used] = '\0'; diff --git a/phpstr/phpstr.h b/phpstr/phpstr.h index ac58c1d..40e2e32 100644 --- a/phpstr/phpstr.h +++ b/phpstr/phpstr.h @@ -105,8 +105,8 @@ PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags); PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length); /* usually only called from within the internal functions */ -#define phpstr_resize(b, s) phpstr_resize_ex((b), (s), 0) -PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size); +#define phpstr_resize(b, s) phpstr_resize_ex((b), (s), 0, 0) +PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error); /* shrink memory chunk to actually used size (+1) */ PHPSTR_API size_t phpstr_shrink(phpstr *buf); -- 2.30.2