Skip to content

Commit a7918a7

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

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
@@ -54,6 +54,10 @@ PHP NEWS
5454
. Fixed bug GH-16292 (Segmentation fault in ext/xmlreader/php_xmlreader.c).
5555
(nielsdos)
5656

57+
- Zlib:
58+
. Fixed bug GH-16326 (Memory management is broken for bad dictionaries.)
59+
(cmb)
60+
5761
10 Oct 2024, PHP 8.4.0RC2
5862

5963
- CGI:

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
@@ -804,35 +804,29 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_
804804
if (zend_hash_num_elements(dictionary) > 0) {
805805
char *dictptr;
806806
zval *cur;
807-
zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary));
807+
zend_string **strings = safe_emalloc(zend_hash_num_elements(dictionary), sizeof(zend_string *), 0);
808808
zend_string **end, **ptr = strings - 1;
809809

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

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

0 commit comments

Comments
 (0)