From 5dc78bade19c1499863689e176de9d6fe867d707 Mon Sep 17 00:00:00 2001 From: Andy Postnikov Date: Tue, 14 Apr 2026 23:17:52 +0200 Subject: [PATCH] Fix segfault in do_operation handler (ext-decimal 2.0.x) Bug was introduced in commit b8b4420 ("Alpha implementation of Number and Rational", Jan 2019) which changed unsupported-operator handling from return FAILURE (1.x) to throw ArithmeticError + return SUCCESS with result zval left uninitialized. The ZEND_TRY_BINARY_OBJECT_OPERATION macro in Zend engine has called do_operation for all operator types (including CONCAT, BW_OR) since PHP 5.6 (commit 089f4967997, Oct 2014). When do_operation throws an exception but returns SUCCESS without initializing result, the VM's exception handler crashes in zval_delref_p. This affects all PHP versions (8.2+), not only PHP 8.5. Fix by setting result to UNDEF before returning SUCCESS for unsupported operators, so the exception handler safely skips cleanup. Co-Authored-By: GLM-5.1 --- src/decimal.c | 1 + src/number.c | 1 + src/rational.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/decimal.c b/src/decimal.c index a5bab69..a4ba9d0 100644 --- a/src/decimal.c +++ b/src/decimal.c @@ -397,6 +397,7 @@ static php_decimal_success_t php_decimal_do_operation_handler(zend_uchar opcode, /* Unsupported op type - return success to avoid casting. */ if (UNEXPECTED(op == NULL)) { php_decimal_operator_not_supported(); + ZVAL_UNDEF(result); return SUCCESS; } diff --git a/src/number.c b/src/number.c index 2970b93..1f9a72c 100644 --- a/src/number.c +++ b/src/number.c @@ -105,6 +105,7 @@ static php_decimal_success_t php_decimal_number_do_operation(zend_uchar opcode, /* Unsupported operator - return success to avoid casting. */ if (UNEXPECTED(func == NULL)) { php_decimal_operator_not_supported(); + ZVAL_UNDEF(result); return SUCCESS; } diff --git a/src/rational.c b/src/rational.c index 1038135..e4d6686 100644 --- a/src/rational.c +++ b/src/rational.c @@ -316,6 +316,7 @@ static php_decimal_success_t php_decimal_rational_do_operation(zend_uchar opcode /* Unsupported operator - return success to avoid casting. */ if (UNEXPECTED(op == NULL)) { php_decimal_operator_not_supported(); + ZVAL_UNDEF(result); return SUCCESS; }