From 55848113f02c65c1f52259bf30514c08fd39ed10 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 14 Oct 2024 19:12:53 +0200 Subject: [PATCH 1/3] Simplify zlib dictionary processing The patch has been contributed by @TimWolla. --- ext/zlib/zlib.c | 69 ++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 4221bceacc8c7..bc3729147b5b5 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -796,62 +796,65 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_ *dict = emalloc(ZSTR_LEN(str)); memcpy(*dict, ZSTR_VAL(str), ZSTR_LEN(str)); *dictlen = ZSTR_LEN(str); - } break; + + return 1; + } case IS_ARRAY: { HashTable *dictionary = Z_ARR_P(option_buffer); + bool result = 1; if (zend_hash_num_elements(dictionary) > 0) { - char *dictptr; - zval *cur; zend_string **strings = safe_emalloc(zend_hash_num_elements(dictionary), sizeof(zend_string *), 0); - zend_string **end, **ptr = strings - 1; + size_t total = 0; + zval *cur; ZEND_HASH_FOREACH_VAL(dictionary, cur) { - *++ptr = zval_get_string(cur); - ZEND_ASSERT(*ptr); - if (ZSTR_LEN(*ptr) == 0 || EG(exception)) { - do { - zend_string_release(*ptr); - } while (--ptr >= strings); - efree(strings); - if (!EG(exception)) { - zend_argument_value_error(2, "must not contain empty strings"); - } - return 0; + zend_string *string = zval_get_string(cur); + ZEND_ASSERT(string); + if (EG(exception)) { + result = 0; + break; + } + if (ZSTR_LEN(string) == 0) { + result = 0; + zend_argument_value_error(2, "must not contain empty strings"); + break; } - if (zend_str_has_nul_byte(*ptr)) { - do { - zend_string_release(*ptr); - } while (--ptr >= strings); - efree(strings); + if (zend_str_has_nul_byte(string)) { + result = 0; zend_argument_value_error(2, "must not contain strings with null bytes"); - return 0; + break; } - *dictlen += ZSTR_LEN(*ptr) + 1; + *dictlen += ZSTR_LEN(string) + 1; + strings[total] = string; + total++; } ZEND_HASH_FOREACH_END(); - dictptr = *dict = emalloc(*dictlen); - ptr = strings; - end = strings + zend_hash_num_elements(dictionary); - do { - memcpy(dictptr, ZSTR_VAL(*ptr), ZSTR_LEN(*ptr)); - dictptr += ZSTR_LEN(*ptr); + char *dictptr = emalloc(*dictlen); + *dict = dictptr; + for (size_t i = 0; i < total; i++) { + zend_string *string = strings[i]; + dictptr = zend_mempcpy(dictptr, ZSTR_VAL(string), ZSTR_LEN(string)); *dictptr++ = 0; - zend_string_release_ex(*ptr, 0); - } while (++ptr != end); + zend_string_release(string); + } efree(strings); + if (!result) { + efree(*dict); + *dict = NULL; + } } - } break; + + return result; + } default: zend_argument_type_error(2, "must be of type zero-terminated string or array, %s given", zend_zval_value_name(option_buffer)); return 0; } } - - return 1; } /* {{{ Initialize an incremental inflate context with the specified encoding */ From 859f4726664fda686aba6231c34857958443913c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 14 Oct 2024 19:15:12 +0200 Subject: [PATCH 2/3] Minor fix and improvement --- ext/zlib/zlib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index bc3729147b5b5..4c767305d6b1f 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -810,9 +810,8 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_ zval *cur; ZEND_HASH_FOREACH_VAL(dictionary, cur) { - zend_string *string = zval_get_string(cur); - ZEND_ASSERT(string); - if (EG(exception)) { + zend_string *string = zval_try_get_string(cur); + if (string == NULL) { result = 0; break; } @@ -855,6 +854,7 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_ return 0; } } + return 1; } /* {{{ Initialize an incremental inflate context with the specified encoding */ From 2990e3e7f702fa9b4da7d9565709472bc175bb24 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 15 Oct 2024 18:29:02 +0200 Subject: [PATCH 3/3] Fix leak --- ext/zlib/zlib.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 4c767305d6b1f..c2a3d3c856d9d 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -815,6 +815,8 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_ result = 0; break; } + *dictlen += ZSTR_LEN(string) + 1; + strings[total++] = string; if (ZSTR_LEN(string) == 0) { result = 0; zend_argument_value_error(2, "must not contain empty strings"); @@ -825,10 +827,6 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_ zend_argument_value_error(2, "must not contain strings with null bytes"); break; } - - *dictlen += ZSTR_LEN(string) + 1; - strings[total] = string; - total++; } ZEND_HASH_FOREACH_END(); char *dictptr = emalloc(*dictlen);