From b7fd773cc6f9f8c0ca0ead2d20177829ce4a5dc1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 16 Oct 2024 12:21:50 +0200 Subject: [PATCH] Refactor zlib dictionary processing (GH-16407) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tim Düsterhus --- ext/zlib/zlib.c | 67 +++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index ec622a681b25..df3d270217d4 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -796,61 +796,62 @@ 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_try_get_string(cur); + if (string == NULL) { + 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"); + 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; } 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; }