From 6c198e380e09ff399cb798558af1567627fbcd37 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 15 Dec 2024 20:09:06 +0100 Subject: [PATCH 1/2] Fix GH-16255: Unexpected nan value in ext/gd/libgd/gd_filter.c Closes GH-17169. --- NEWS | 4 ++++ ext/gd/gd.c | 19 ++++++++++++++++++- ext/gd/tests/gh16255.phpt | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 ext/gd/tests/gh16255.phpt diff --git a/NEWS b/NEWS index 437c704c25e..43505d08cee 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,10 @@ PHP NEWS . Fixed bug GH-13437 (FPM: ERROR: scoreboard: failed to lock (already locked)). (Jakub Zelenka) +- GD: + . Fixed bug GH-16255 (Unexpected nan value in ext/gd/libgd/gd_filter.c). + (nielsdos, cmb) + - Iconv: . Fixed bug GH-17047 (UAF on iconv filter failure). (nielsdos) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 13da099b335..847e0835bad 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3433,7 +3433,24 @@ PHP_FUNCTION(imageconvolution) } } } - res = gdImageConvolution(im_src, matrix, (float)div, (float)offset); + + if (UNEXPECTED(!zend_finite(div))) { + zend_argument_value_error(3, "must be finite"); + RETURN_THROWS(); + } + + float div_float = (float) div; + if (UNEXPECTED(div_float == 0.0f)) { + zend_argument_value_error(3, "must not be 0"); + RETURN_THROWS(); + } + + if (UNEXPECTED(!zend_finite(offset))) { + zend_argument_value_error(4, "must be finite"); + RETURN_THROWS(); + } + + res = gdImageConvolution(im_src, matrix, div_float, (float) offset); if (res) { RETURN_TRUE; diff --git a/ext/gd/tests/gh16255.phpt b/ext/gd/tests/gh16255.phpt new file mode 100644 index 00000000000..147dc5adf37 --- /dev/null +++ b/ext/gd/tests/gh16255.phpt @@ -0,0 +1,34 @@ +--TEST-- +GH-16255 (Unexpected nan value in ext/gd/libgd/gd_filter.c) +--EXTENSIONS-- +gd +--CREDITS-- +cmb69 +--FILE-- +getMessage(), "\n"; +} + +try { + imageconvolution($im, $matrix, 2.225E-307, 1.0); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +try { + imageconvolution($im, $matrix, 1, NAN); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +imageconvolution(): Argument #3 ($divisor) must be finite +imageconvolution(): Argument #3 ($divisor) must not be 0 +imageconvolution(): Argument #4 ($offset) must be finite From 2104097a79d8c726bf9efbb7c2ed17ee72bb7022 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:24:31 +0100 Subject: [PATCH 2/2] Fix GH-17140 (Assertion failure in JIT trace exit with ZEND_FETCH_DIM_FUNC_ARG) ZEND_FETCH_DIM_FUNC_ARG should also be repeated on undefined access, consistent to how ZEND_FETCH_DIM_R is handled. The opcode was just missing from the assertion list. Closes GH-17148. Co-authored-by: Dmitry Stogov --- NEWS | 2 ++ ext/opcache/jit/zend_jit_trace.c | 2 +- ext/opcache/tests/jit/gh17140_1.phpt | 33 +++++++++++++++++++++++ ext/opcache/tests/jit/gh17140_2.phpt | 40 ++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/jit/gh17140_1.phpt create mode 100644 ext/opcache/tests/jit/gh17140_2.phpt diff --git a/NEWS b/NEWS index 675ca9f8dec..b44a0bcaaa0 100644 --- a/NEWS +++ b/NEWS @@ -43,6 +43,8 @@ PHP NEWS - Opcache: . opcache_get_configuration() properly reports jit_prof_threshold. (cmb) + . Fixed bug GH-17140 (Assertion failure in JIT trace exit with + ZEND_FETCH_DIM_FUNC_ARG). (nielsdos, Dmitry) - PCNTL: . Fix memory leak in cleanup code of pcntl_exec() when a non stringable diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index da66a903c17..8f20c85da05 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -8585,7 +8585,7 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf if (op->opcode == ZEND_FETCH_DIM_IS || op->opcode == ZEND_FETCH_OBJ_IS) { ZVAL_NULL(EX_VAR_NUM(i)); } else { - assert(op->opcode == ZEND_FETCH_DIM_R || op->opcode == ZEND_FETCH_LIST_R || op->opcode == ZEND_FETCH_OBJ_R); + ZEND_ASSERT(op->opcode == ZEND_FETCH_DIM_R || op->opcode == ZEND_FETCH_LIST_R || op->opcode == ZEND_FETCH_OBJ_R || op->opcode == ZEND_FETCH_DIM_FUNC_ARG || op->opcode == ZEND_FETCH_OBJ_FUNC_ARG); repeat_last_opline = 1; } } else { diff --git a/ext/opcache/tests/jit/gh17140_1.phpt b/ext/opcache/tests/jit/gh17140_1.phpt new file mode 100644 index 00000000000..a37277f69ba --- /dev/null +++ b/ext/opcache/tests/jit/gh17140_1.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-17140 (Assertion failure in JIT trace exit with ZEND_FETCH_DIM_FUNC_ARG) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1254 +opcache.jit_buffer_size=32M +opcache.jit_hot_func=1 +opcache.jit_hot_side_exit=1 +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $i in %s on line %d + +Warning: Undefined array key 0 in %s on line %d +NULL + +Warning: Undefined variable $i in %s on line %d + +Warning: Undefined array key 0 in %s on line %d +NULL + +Warning: Undefined array key 0 in %s on line %d +NULL diff --git a/ext/opcache/tests/jit/gh17140_2.phpt b/ext/opcache/tests/jit/gh17140_2.phpt new file mode 100644 index 00000000000..9ef3177c75f --- /dev/null +++ b/ext/opcache/tests/jit/gh17140_2.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-17140 (Assertion failure in JIT trace exit with ZEND_FETCH_OBJ_FUNC_ARG) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1254 +opcache.jit_buffer_size=32M +opcache.jit_hot_func=1 +opcache.jit_hot_side_exit=1 +--FILE-- +b); + } +} +function test() { + $a['x'] = new X; + for ($fusion = 0; $i < 3; $i++) { + var_dump($a['x']->b); + } +} +test(); +?> +--EXPECTF-- +Warning: Undefined variable $i in %s on line %d + +Warning: Undefined property: Foo\X::$b in %s on line %d +NULL + +Warning: Undefined variable $i in %s on line %d + +Warning: Undefined property: Foo\X::$b in %s on line %d +NULL + +Warning: Undefined property: Foo\X::$b in %s on line %d +NULL