From 9367cfcaa95730872992aaa0366f5b3c084659b4 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Sun, 11 Aug 2024 18:35:15 +0200 Subject: [PATCH 1/2] ext/gmp: Be more strict on exponent/shift value --- ext/gmp/gmp.c | 19 ++++++++++- ext/gmp/tests/gmp_pow_error.phpt | 41 ++++++++++++++++++++++++ ext/gmp/tests/gmp_shift_left_error.phpt | 41 ++++++++++++++++++++++++ ext/gmp/tests/gmp_shift_right_error.phpt | 41 ++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 ext/gmp/tests/gmp_pow_error.phpt create mode 100644 ext/gmp/tests/gmp_shift_left_error.phpt create mode 100644 ext/gmp/tests/gmp_shift_right_error.phpt diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 752d18ec56433..8bb3fcadf65ac 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -339,7 +339,24 @@ static zend_object *gmp_clone_obj(zend_object *obj) /* {{{ */ /* }}} */ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2, uint8_t opcode) { - zend_long shift = zval_get_long(op2); + bool failed = true; + zend_long shift = zval_try_get_long(op2, &failed); + if (failed) { + //char operator_sigil[2]; + char *operator_sigil; + if (opcode == ZEND_POW) { + operator_sigil = "**"; + } else if (opcode == ZEND_SL) { + operator_sigil = "<<"; + } else { + ZEND_ASSERT(opcode == ZEND_SR); + operator_sigil = ">>"; + } + + zend_type_error("Unsupported operand types: GMP %s %s", operator_sigil, zend_zval_value_name(op2)); + ZVAL_UNDEF(return_value); + return; + } if (shift < 0) { zend_throw_error( diff --git a/ext/gmp/tests/gmp_pow_error.phpt b/ext/gmp/tests/gmp_pow_error.phpt new file mode 100644 index 0000000000000..5ade76878fc69 --- /dev/null +++ b/ext/gmp/tests/gmp_pow_error.phpt @@ -0,0 +1,41 @@ +--TEST-- +Native exponential with invalid exponent +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n ** new stdClass()); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n ** STDERR); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n ** []); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} + + +echo "Done\n"; +?> +--EXPECT-- +TypeError: Unsupported operand types: GMP ** string +TypeError: Unsupported operand types: GMP ** stdClass +TypeError: Unsupported operand types: GMP ** resource +TypeError: Unsupported operand types: GMP ** array +Done diff --git a/ext/gmp/tests/gmp_shift_left_error.phpt b/ext/gmp/tests/gmp_shift_left_error.phpt new file mode 100644 index 0000000000000..283295fd58f8c --- /dev/null +++ b/ext/gmp/tests/gmp_shift_left_error.phpt @@ -0,0 +1,41 @@ +--TEST-- +Native shift left with invalid op2 +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n << new stdClass()); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n << STDERR); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n << []); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} + + +echo "Done\n"; +?> +--EXPECT-- +TypeError: Unsupported operand types: GMP << string +TypeError: Unsupported operand types: GMP << stdClass +TypeError: Unsupported operand types: GMP << resource +TypeError: Unsupported operand types: GMP << array +Done diff --git a/ext/gmp/tests/gmp_shift_right_error.phpt b/ext/gmp/tests/gmp_shift_right_error.phpt new file mode 100644 index 0000000000000..26c6adb125a5b --- /dev/null +++ b/ext/gmp/tests/gmp_shift_right_error.phpt @@ -0,0 +1,41 @@ +--TEST-- +Native shift right with invalid op2 +--EXTENSIONS-- +gmp +--FILE-- +> "nonsense"); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n >> new stdClass()); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n >> STDERR); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +try { + $n = gmp_init("6"); + var_dump($n >> []); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} + + +echo "Done\n"; +?> +--EXPECT-- +TypeError: Unsupported operand types: GMP >> string +TypeError: Unsupported operand types: GMP >> stdClass +TypeError: Unsupported operand types: GMP >> resource +TypeError: Unsupported operand types: GMP >> array +Done From b9d646323bb12e9a422d135120a60d4698869168 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Mon, 12 Aug 2024 17:32:52 +0200 Subject: [PATCH 2/2] Address review comments --- ext/gmp/gmp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 8bb3fcadf65ac..b50cfe2efbb83 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -342,8 +342,7 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva bool failed = true; zend_long shift = zval_try_get_long(op2, &failed); if (failed) { - //char operator_sigil[2]; - char *operator_sigil; + const char *operator_sigil; if (opcode == ZEND_POW) { operator_sigil = "**"; } else if (opcode == ZEND_SL) {