Skip to content

Commit

Permalink
fix Bug #46026: bz2.decompress/zlib.inflate filter tries to decompres…
Browse files Browse the repository at this point in the history
…s after end of stream

[DOC] add concatenation option to bz2.decompress stream filter
  • Loading branch information
Greg Beaver committed Oct 11, 2008
1 parent 9552f1a commit 59e5288
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 11 deletions.
4 changes: 3 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ PHP NEWS
- Changed openssl info to show the shared library version number. (Scott)

- Added ability to send user defined HTTP headers with SOAP request.
(Brain J.France, Dmitry)
(Brian J.France, Dmitry)
- Added concatenation option to bz2.decompress stream filter.
(Keisial at gmail dot com, Greg)

- Fixed bug causing the algorithm parameter of mhash() to be modified. (Scott)

Expand Down
61 changes: 54 additions & 7 deletions ext/bz2/bz2_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,24 @@

/* {{{ data structure */

enum strm_status {
PHP_BZ2_UNITIALIZED,
PHP_BZ2_RUNNING,
PHP_BZ2_FINISHED
};

typedef struct _php_bz2_filter_data {
int persistent;
bz_stream strm;
char *inbuf;
size_t inbuf_len;
char *outbuf;
size_t outbuf_len;

/* Decompress options */
enum strm_status status;
unsigned int small_footprint : 1;
unsigned int expect_concatenated : 1;
} php_bz2_filter_data;

/* }}} */
Expand Down Expand Up @@ -82,6 +93,21 @@ static php_stream_filter_status_t php_bz2_decompress_filter(

bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
while (bin < bucket->buflen) {
if (data->status == PHP_BZ2_UNITIALIZED) {
status = BZ2_bzDecompressInit(streamp, 0, data->small_footprint);

if (BZ_OK != status) {
return PSFS_ERR_FATAL;
}

data->status = PHP_BZ2_RUNNING;
}

if (data->status != PHP_BZ2_RUNNING) {
consumed += bucket->buflen;
break;
}

desired = bucket->buflen - bin;
if (desired > data->inbuf_len) {
desired = data->inbuf_len;
Expand All @@ -90,7 +116,15 @@ static php_stream_filter_status_t php_bz2_decompress_filter(
data->strm.avail_in = desired;

status = BZ2_bzDecompress(&(data->strm));
if (status != BZ_OK && status != BZ_STREAM_END) {

if (status == BZ_STREAM_END) {
BZ2_bzDecompressEnd(&(data->strm));
if (data->expect_concatenated) {
data->status = PHP_BZ2_UNITIALIZED;
} else {
data->status = PHP_BZ2_FINISHED;
}
} else if (status != BZ_OK) {
/* Something bad happened */
php_stream_bucket_delref(bucket TSRMLS_CC);
return PSFS_ERR_FATAL;
Expand All @@ -115,10 +149,11 @@ static php_stream_filter_status_t php_bz2_decompress_filter(
return PSFS_PASS_ON;
}
}

php_stream_bucket_delref(bucket TSRMLS_CC);
}

if (flags & PSFS_FLAG_FLUSH_CLOSE) {
if ((data->status == PHP_BZ2_RUNNING) && (flags & PSFS_FLAG_FLUSH_CLOSE)) {
/* Spit it out! */
status = BZ_OK;
while (status == BZ_OK) {
Expand Down Expand Up @@ -148,7 +183,9 @@ static void php_bz2_decompress_dtor(php_stream_filter *thisfilter TSRMLS_DC)
{
if (thisfilter && thisfilter->abstract) {
php_bz2_filter_data *data = thisfilter->abstract;
BZ2_bzDecompressEnd(&(data->strm));
if (data->status == PHP_BZ2_RUNNING) {
BZ2_bzDecompressEnd(&(data->strm));
}
pefree(data->inbuf, data->persistent);
pefree(data->outbuf, data->persistent);
pefree(data, data->persistent);
Expand Down Expand Up @@ -275,7 +312,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi
{
php_stream_filter_ops *fops = NULL;
php_bz2_filter_data *data;
int status;
int status = BZ_OK;

/* Create this filter */
data = pecalloc(1, sizeof(php_bz2_filter_data), persistent);
Expand Down Expand Up @@ -307,12 +344,22 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi
}

if (strcasecmp(filtername, "bzip2.decompress") == 0) {
int smallFootprint = 0;
data->small_footprint = 0;
data->expect_concatenated = 0;

if (filterparams) {
zval **tmpzval = NULL;

if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) {

if (SUCCESS == zend_hash_find(HASH_OF(filterparams), "concatenated", sizeof("concatenated"), (void **) &tmpzval) ) {
SEPARATE_ZVAL(tmpzval);
convert_to_boolean_ex(tmpzval);
data->expect_concatenated = Z_LVAL_PP(tmpzval);
zval_ptr_dtor(tmpzval);
tmpzval = NULL;
}

zend_hash_find(HASH_OF(filterparams), "small", sizeof("small"), (void **) &tmpzval);
} else {
tmpzval = &filterparams;
Expand All @@ -321,12 +368,12 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi
if (tmpzval) {
SEPARATE_ZVAL(tmpzval);
convert_to_boolean_ex(tmpzval);
smallFootprint = Z_LVAL_PP(tmpzval);
data->small_footprint = Z_LVAL_PP(tmpzval);
zval_ptr_dtor(tmpzval);
}
}

status = BZ2_bzDecompressInit(&(data->strm), 0, smallFootprint);
data->status = PHP_BZ2_UNITIALIZED;
fops = &php_bz2_decompress_ops;
} else if (strcasecmp(filtername, "bzip2.compress") == 0) {
int blockSize100k = PHP_BZ2_FILTER_DEFAULT_BLOCKSIZE;
Expand Down
19 changes: 16 additions & 3 deletions ext/zlib/zlib_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ typedef struct _php_zlib_filter_data {
size_t inbuf_len;
char *outbuf;
size_t outbuf_len;
zend_bool finished;
} php_zlib_filter_data;

/* }}} */
Expand Down Expand Up @@ -81,6 +82,12 @@ static php_stream_filter_status_t php_zlib_inflate_filter(

bucket = php_stream_bucket_make_writeable(buckets_in->head TSRMLS_CC);
while (bin < bucket->buflen) {

if (data->finished) {
consumed += bucket->buflen;
break;
}

desired = bucket->buflen - bin;
if (desired > data->inbuf_len) {
desired = data->inbuf_len;
Expand All @@ -89,7 +96,10 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
data->strm.avail_in = desired;

status = inflate(&(data->strm), flags & PSFS_FLAG_FLUSH_CLOSE ? Z_FINISH : Z_SYNC_FLUSH);
if (status != Z_OK && status != Z_STREAM_END) {
if (status == Z_STREAM_END) {
inflateEnd(&(data->strm));
data->finished = '\1';
} else if (status != Z_OK) {
/* Something bad happened */
php_stream_bucket_delref(bucket TSRMLS_CC);
return PSFS_ERR_FATAL;
Expand Down Expand Up @@ -117,7 +127,7 @@ static php_stream_filter_status_t php_zlib_inflate_filter(
php_stream_bucket_delref(bucket TSRMLS_CC);
}

if (flags & PSFS_FLAG_FLUSH_CLOSE) {
if (!data->finished && flags & PSFS_FLAG_FLUSH_CLOSE) {
/* Spit it out! */
status = Z_OK;
while (status == Z_OK) {
Expand Down Expand Up @@ -145,7 +155,9 @@ static void php_zlib_inflate_dtor(php_stream_filter *thisfilter TSRMLS_DC)
{
if (thisfilter && thisfilter->abstract) {
php_zlib_filter_data *data = thisfilter->abstract;
inflateEnd(&(data->strm));
if (!data->finished) {
inflateEnd(&(data->strm));
}
pefree(data->inbuf, data->persistent);
pefree(data->outbuf, data->persistent);
pefree(data, data->persistent);
Expand Down Expand Up @@ -329,6 +341,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f
}

/* RFC 1951 Inflate */
data->finished = '\0';
status = inflateInit2(&(data->strm), windowBits);
fops = &php_zlib_inflate_ops;
} else if (strcasecmp(filtername, "zlib.deflate") == 0) {
Expand Down

0 comments on commit 59e5288

Please sign in to comment.