Skip to content

Commit d4c88a2

Browse files
authored
ext/bz2: Check int params of bzcompress() are correct (#16108)
Also add a TODO to check the length of the source strings
1 parent 4a8cd31 commit d4c88a2

File tree

4 files changed

+68
-30
lines changed

4 files changed

+68
-30
lines changed

UPGRADING

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ PHP 8.5 UPGRADE NOTES
1919
1. Backward Incompatible Changes
2020
========================================
2121

22+
- BZ2:
23+
. bzcompress() now throws a ValueError when $block_size is not between
24+
1 and 9.
25+
. bzcompress() now throws a ValueError when work_factor is not between
26+
0 and 250.
27+
2228
- LDAP:
2329
. ldap_get_option() and ldap_set_option() now throw a ValueError when
2430
passing an invalid option.

ext/bz2/bz2.c

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -439,40 +439,40 @@ PHP_FUNCTION(bzerror)
439439
/* {{{ Compresses a string into BZip2 encoded data */
440440
PHP_FUNCTION(bzcompress)
441441
{
442-
char *source; /* Source data to compress */
443-
zend_long zblock_size = 0; /* Optional block size to use */
444-
zend_long zwork_factor = 0;/* Optional work factor to use */
445-
zend_string *dest = NULL; /* Destination to place the compressed data into */
446-
int error, /* Error Container */
447-
block_size = 4, /* Block size for compression algorithm */
448-
work_factor = 0, /* Work factor for compression algorithm */
449-
argc = ZEND_NUM_ARGS(); /* Argument count */
450-
size_t source_len; /* Length of the source data */
451-
unsigned int dest_len; /* Length of the destination buffer */
452-
453-
if (zend_parse_parameters(argc, "s|ll", &source, &source_len, &zblock_size, &zwork_factor) == FAILURE) {
442+
char *source; /* Source data to compress */
443+
zend_long zblock_size = 4; /* Block size for compression algorithm */
444+
zend_long zwork_factor = 0; /* Work factor for compression algorithm */
445+
zend_string *dest = NULL; /* Destination to place the compressed data into */
446+
size_t source_len; /* Length of the source data */
447+
unsigned int dest_len; /* Length of the destination buffer */
448+
449+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ll", &source, &source_len, &zblock_size, &zwork_factor) == FAILURE) {
454450
RETURN_THROWS();
455451
}
456452

453+
if (zblock_size < 1 || zblock_size > 9) {
454+
zend_argument_value_error(2, "must be between 1 and 9");
455+
RETURN_THROWS();
456+
}
457+
int block_size = (int) zblock_size;
458+
459+
if (zwork_factor < 0 || zwork_factor > 250) {
460+
zend_argument_value_error(3, "must be between 0 and 250");
461+
RETURN_THROWS();
462+
}
463+
int work_factor = (int) zwork_factor;
464+
457465
/* Assign them to easy to use variables, dest_len is initially the length of the data
458466
+ .01 x length of data + 600 which is the largest size the results of the compression
459467
could possibly be, at least that's what the libbz2 docs say (thanks to jeremy@nirvani.net
460468
for pointing this out). */
469+
// TODO Check source string length fits in unsigned int
461470
dest_len = (unsigned int) (source_len + (0.01 * source_len) + 600);
462471

463472
/* Allocate the destination buffer */
464473
dest = zend_string_alloc(dest_len, 0);
465474

466-
/* Handle the optional arguments */
467-
if (argc > 1) {
468-
block_size = zblock_size;
469-
}
470-
471-
if (argc > 2) {
472-
work_factor = zwork_factor;
473-
}
474-
475-
error = BZ2_bzBuffToBuffCompress(ZSTR_VAL(dest), &dest_len, source, source_len, block_size, 0, work_factor);
475+
int error = BZ2_bzBuffToBuffCompress(ZSTR_VAL(dest), &dest_len, source, source_len, block_size, 0, work_factor);
476476
if (error != BZ_OK) {
477477
zend_string_efree(dest);
478478
RETURN_LONG(error);
@@ -512,6 +512,7 @@ PHP_FUNCTION(bzdecompress)
512512
RETURN_FALSE;
513513
}
514514

515+
// TODO Check source string length fits in unsigned int
515516
bzs.next_in = source;
516517
bzs.avail_in = source_len;
517518

ext/bz2/tests/005.phpt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ Getting lost within myself
1111
Nothing matters no one else";
1212

1313
var_dump(bzcompress(1,1,1));
14-
var_dump(bzcompress($string, 100));
15-
var_dump(bzcompress($string, 100, -1));
16-
var_dump(bzcompress($string, 100, 1000));
17-
var_dump(bzcompress($string, -1, 1));
1814

1915
$data = bzcompress($string);
2016
$data2 = bzcompress($string, 1, 10);
@@ -35,10 +31,6 @@ echo "Done\n";
3531
?>
3632
--EXPECTF--
3733
string(%d) "BZ%a"
38-
int(-2)
39-
int(-2)
40-
int(-2)
41-
int(-2)
4234
int(-5)
4335
int(-5)
4436
int(-5)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
bzcompress(): providing invalid options
3+
--EXTENSIONS--
4+
bz2
5+
--FILE--
6+
<?php
7+
8+
$string = "Life it seems, will fade away
9+
Drifting further everyday
10+
Getting lost within myself
11+
Nothing matters no one else";
12+
13+
try {
14+
var_dump(bzcompress($string, 0));
15+
} catch (Throwable $e) {
16+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
17+
}
18+
try {
19+
var_dump(bzcompress($string, 100));
20+
} catch (Throwable $e) {
21+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
22+
}
23+
try {
24+
var_dump(bzcompress($string, work_factor: -1));
25+
} catch (Throwable $e) {
26+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
27+
}
28+
try {
29+
var_dump(bzcompress($string, work_factor: 255));
30+
} catch (Throwable $e) {
31+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
32+
}
33+
34+
?>
35+
--EXPECT--
36+
ValueError: bzcompress(): Argument #2 ($block_size) must be between 1 and 9
37+
ValueError: bzcompress(): Argument #2 ($block_size) must be between 1 and 9
38+
ValueError: bzcompress(): Argument #3 ($work_factor) must be between 0 and 250
39+
ValueError: bzcompress(): Argument #3 ($work_factor) must be between 0 and 250

0 commit comments

Comments
 (0)