From ede8adb2e2013eafe67edb64fc8d5fa62f40cb7d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 6 Apr 2023 21:55:11 +0200 Subject: [PATCH] Fix GH-11016: Heap buffer overflow in ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER (#11021) Not enough space was reserved for the packed resulting array because of some confusion in the meaning of nr of used slots vs nr of elements. Co-authored-by: Ilija Tovilo --- Zend/tests/gh11016.phpt | 20 ++++++++++++++++++++ Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/gh11016.phpt diff --git a/Zend/tests/gh11016.phpt b/Zend/tests/gh11016.phpt new file mode 100644 index 00000000000..7946166b176 --- /dev/null +++ b/Zend/tests/gh11016.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-11016 (Heap buffer overflow in ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER) +--FILE-- + 0, ...[1, 1, 1]]; +print_r($x); +?> +--EXPECT-- +Array +( + [6] => 0 + [7] => 1 + [8] => 1 + [9] => 1 +) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7ef8cf1922d..88b46a641d0 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6128,7 +6128,7 @@ ZEND_VM_C_LABEL(add_unpack_again): zval *val; if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) { - zend_hash_extend(result_ht, zend_hash_num_elements(result_ht) + zend_hash_num_elements(ht), 1); + zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); ZEND_HASH_FILL_PACKED(result_ht) { ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { if (UNEXPECTED(Z_ISREF_P(val)) && diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 19149c8c18e..d44be7760c4 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2652,7 +2652,7 @@ add_unpack_again: zval *val; if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) { - zend_hash_extend(result_ht, zend_hash_num_elements(result_ht) + zend_hash_num_elements(ht), 1); + zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); ZEND_HASH_FILL_PACKED(result_ht) { ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { if (UNEXPECTED(Z_ISREF_P(val)) &&