From 300e745473fa69c98724e6a08f20ad0553d441c4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 8 Oct 2024 23:50:56 +0200 Subject: [PATCH] Fix out of bound writes to SafeArray data Converting PHP arrays to Variants originally supported almost arbitrary numeric arrays, possibly filling gaps with NULL values. This is broken as of PHP 7.0.0[1] so that the SafeArray only has as many elements as the PHP array. Thus, unless the array is a list, some elements may be written outside of the SafeArray data. To avoid breaking userland code after that long time, we do not restore the original behavior, but instead only suppress the erroneous writes. To avoid the need to split the regression test for 32bit and 64bit Windows, we suppress the "max number 4294967295 of elements in safe array exceeded" warning, which only occurs for 64bit versions. [1] --- ext/com_dotnet/com_variant.c | 7 ++--- ext/com_dotnet/tests/variant_variation.phpt | 30 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 ext/com_dotnet/tests/variant_variation.phpt diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c index b40ac6a5c31f9..edb9d771aea8f 100644 --- a/ext/com_dotnet/com_variant.c +++ b/ext/com_dotnet/com_variant.c @@ -26,8 +26,7 @@ /* create an automation SafeArray from a PHP array. * Only creates a single-dimensional array of variants. - * The keys of the PHP hash MUST be numeric. If the array - * is sparse, then the gaps will be filled with NULL variants */ + * The keys of the PHP hash MUST be numeric. */ static void safe_array_from_zval(VARIANT *v, zval *z, int codepage) { SAFEARRAY *sa = NULL; @@ -71,7 +70,9 @@ static void safe_array_from_zval(VARIANT *v, zval *z, int codepage) break; } zend_hash_get_current_key_ex(Z_ARRVAL_P(z), &strindex, &intindex, &pos); - php_com_variant_from_zval(&va[intindex], item, codepage); + if (intindex < bound.cElements) { + php_com_variant_from_zval(&va[intindex], item, codepage); + } } /* Unlock it and stuff it into our variant */ diff --git a/ext/com_dotnet/tests/variant_variation.phpt b/ext/com_dotnet/tests/variant_variation.phpt new file mode 100644 index 0000000000000..c1f821715a14d --- /dev/null +++ b/ext/com_dotnet/tests/variant_variation.phpt @@ -0,0 +1,30 @@ +--TEST-- +Testing variant arrays +--EXTENSIONS-- +com_dotnet +--FILE-- + [2 => 1, 1 => 2, 0 => 3], + "off" => [2 => 1, 1 => 2, 3], + "negative" => [-1 => 42], +]; +foreach ($arrays as $desc => $array) { + echo "-- $desc --\n"; + $v = new variant($array); + foreach ($v as $val) { + var_dump($val); + } +} +?> +--EXPECTF-- +-- order -- +int(3) +int(2) +int(1) +-- off -- +NULL +int(2) +int(1) +-- negative -- +%ANULL