Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 12 additions & 22 deletions brotli.c
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ typedef struct _php_brotli_stream_data {
php_brotli_context ctx;
BrotliDecoderResult result;
php_stream *stream;
uint8_t *input_buf;
} php_brotli_stream_data;

#define STREAM_DATA_FROM_STREAM() \
Expand All @@ -822,6 +823,10 @@ static int php_brotli_decompress_close(php_stream *stream,

php_brotli_context_close(&self->ctx);

if (self->input_buf) {
efree(self->input_buf);
}

efree(self);

stream->abstract = NULL;
Expand All @@ -845,48 +850,33 @@ static ssize_t php_brotli_decompress_read(php_stream *stream,
STREAM_DATA_FROM_STREAM();

/* input */
uint8_t *input = (uint8_t *)emalloc(PHP_BROTLI_BUFFER_SIZE);
if (!input) {
#if PHP_VERSION_ID < 70400
return 0;
#else
return -1;
#endif
if (!self->input_buf) {
self->input_buf = emalloc(PHP_BROTLI_BUFFER_SIZE);
}

if (self->result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
if (php_stream_eof(self->stream)) {
/* corrupt input */
efree(input);
#if PHP_VERSION_ID < 70400
return 0;
#else
return -1;
#endif
}
self->ctx.available_in = php_stream_read(self->stream, input,
self->ctx.available_in = php_stream_read(self->stream, self->input_buf,
PHP_BROTLI_BUFFER_SIZE);
if (!self->ctx.available_in) {
efree(input);
#if PHP_VERSION_ID < 70400
return 0;
#else
return -1;
#endif
}
self->ctx.next_in = input;
self->ctx.next_in = self->input_buf;
}

/* output */
uint8_t *output = (uint8_t *)emalloc(count);
if (!output) {
efree(input);
#if PHP_VERSION_ID < 70400
return 0;
#else
return -1;
#endif
}
self->ctx.available_out = count;
self->ctx.next_out = output;

Expand All @@ -912,15 +902,15 @@ static ssize_t php_brotli_decompress_read(php_stream *stream,
break;
}
self->ctx.available_in = php_stream_read(self->stream,
input, count);
self->ctx.next_in = input;
self->input_buf,
PHP_BROTLI_BUFFER_SIZE);
self->ctx.next_in = self->input_buf;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
} else {
/* decoder error */
break;
}
}

efree(input);
efree(output);

return ret;
Expand Down
42 changes: 42 additions & 0 deletions tests/streams_007.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
compress.brotli streams read with chunk size exceeding internal buffer
--FILE--
<?php
$file = dirname(__FILE__) . '/streams_007.out';

// PHP_BROTLI_BUFFER_SIZE is 1 << 19 (524288). Use a payload that does not
// compress (so the on-disk size also exceeds the internal buffer) and a read
// chunk larger than that, exercising the NEEDS_MORE_INPUT path with
// count > PHP_BROTLI_BUFFER_SIZE.
$chunk = 1024 * 1024; // 1 MiB > 524288
$data = random_bytes(1024 * 1024); // uncompressible payload
var_dump(strlen($data) > 524288);

echo "Compress\n";
$dst = fopen('compress.brotli://' . $file, 'wb');
var_dump(fwrite($dst, $data) === strlen($data));
var_dump(fclose($dst));
var_dump(filesize($file) > 524288);

echo "Decompress\n";
$fp = fopen('compress.brotli://' . $file, 'rb');
stream_set_chunk_size($fp, $chunk);
$out = stream_get_contents($fp);
var_dump(fclose($fp));
var_dump(strlen($out) === strlen($data));
var_dump($out === $data);

@unlink($file);
?>
===DONE===
--EXPECTF--
bool(true)
Compress
bool(true)
bool(true)
bool(true)
Decompress
bool(true)
bool(true)
bool(true)
===DONE===
Loading