Skip to content

Commit 631c04e

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix GH-16326: Memory management is broken for bad dictionaries
2 parents 5c8f42f + d94be24 commit 631c04e

File tree

3 files changed

+43
-19
lines changed

3 files changed

+43
-19
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ PHP NEWS
5050
. Fixed bug GH-16292 (Segmentation fault in ext/xmlreader/php_xmlreader.c).
5151
(nielsdos)
5252

53+
- Zlib:
54+
. Fixed bug GH-16326 (Memory management is broken for bad dictionaries.)
55+
(cmb)
56+
5357
24 Oct 2024, PHP 8.3.13
5458

5559
- Calendar:

ext/zlib/tests/gh16326.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
GH-16326 (Memory management is broken for bad dictionaries)
3+
--EXTENSIONS--
4+
zlib
5+
--FILE--
6+
<?php
7+
try {
8+
deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => [" ", ""]]);
9+
} catch (ValueError $ex) {
10+
echo $ex->getMessage(), "\n";
11+
}
12+
try {
13+
deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => ["hello", "wor\0ld"]]);
14+
} catch (ValueError $ex) {
15+
echo $ex->getMessage(), "\n";
16+
}
17+
try {
18+
deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => [" ", new stdClass]]);
19+
} catch (Error $ex) {
20+
echo $ex->getMessage(), "\n";
21+
}
22+
?>
23+
--EXPECT--
24+
deflate_init(): Argument #2 ($options) must not contain empty strings
25+
deflate_init(): Argument #2 ($options) must not contain strings with null bytes
26+
Object of class stdClass could not be converted to string

ext/zlib/zlib.c

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -805,35 +805,29 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_
805805
if (zend_hash_num_elements(dictionary) > 0) {
806806
char *dictptr;
807807
zval *cur;
808-
zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary));
808+
zend_string **strings = safe_emalloc(zend_hash_num_elements(dictionary), sizeof(zend_string *), 0);
809809
zend_string **end, **ptr = strings - 1;
810810

811811
ZEND_HASH_FOREACH_VAL(dictionary, cur) {
812-
size_t i;
813-
814812
*++ptr = zval_get_string(cur);
815-
if (!*ptr || ZSTR_LEN(*ptr) == 0 || EG(exception)) {
816-
if (*ptr) {
817-
efree(*ptr);
818-
}
819-
while (--ptr >= strings) {
820-
efree(ptr);
821-
}
813+
ZEND_ASSERT(*ptr);
814+
if (ZSTR_LEN(*ptr) == 0 || EG(exception)) {
815+
do {
816+
zend_string_release(*ptr);
817+
} while (--ptr >= strings);
822818
efree(strings);
823819
if (!EG(exception)) {
824820
zend_argument_value_error(2, "must not contain empty strings");
825821
}
826822
return 0;
827823
}
828-
for (i = 0; i < ZSTR_LEN(*ptr); i++) {
829-
if (ZSTR_VAL(*ptr)[i] == 0) {
830-
do {
831-
efree(ptr);
832-
} while (--ptr >= strings);
833-
efree(strings);
834-
zend_argument_value_error(2, "must not contain strings with null bytes");
835-
return 0;
836-
}
824+
if (zend_str_has_nul_byte(*ptr)) {
825+
do {
826+
zend_string_release(*ptr);
827+
} while (--ptr >= strings);
828+
efree(strings);
829+
zend_argument_value_error(2, "must not contain strings with null bytes");
830+
return 0;
837831
}
838832

839833
*dictlen += ZSTR_LEN(*ptr) + 1;

0 commit comments

Comments
 (0)