Skip to content

Commit 334f9db

Browse files
committed
Zend: handle IS_UNDEF in the generic conversion helpers that still lack it
IS_UNDEF is a legitimate runtime tag that internal code can obtain from an object property table, and the generic conversion helpers in zend_operators.c are ZEND_API entry points taking an arbitrary zval. Some already account for that and some do not: handled: zendi_try_get_long(), zval_get_long_func(), __zval_get_string_func(), _convert_to_string() missing: _zendi_try_convert_scalar_to_number(), convert_to_long(), convert_to_double(), convert_to_boolean(), zval_get_double_func() The asymmetry is what is left after two point fixes. 2b38384 taught zval_try_get_long() about IS_REFERENCE and 9e1b285 (GH-22142) taught zendi_try_get_long() about IS_UNDEF, each by adding the tag to the one function that had been reported. The siblings were not revisited, so zval_get_long(undef) returns 0 while zval_get_double(undef) reaches ZEND_UNREACHABLE(): an assertion failure in a debug build, undefined behaviour in a release build. Add the missing cases to arms that already express the intended result, so IS_UNDEF behaves as IS_NULL does for the cast helpers and produces a normal TypeError for the operator helper, matching the bitwise operators which are already safe through zendi_try_get_long(). increment_function() and decrement_function() are deliberately not changed. IS_UNDEF must not reach them: every VM handler normalizes it to IS_NULL before the call (zend_vm_def.h), and the JIT asserts the precondition outright (zend_jit_helpers.c). Accepting it there would weaken a check another subsystem relies on. No behaviour changes for any tag that works today, and no catch-all default is added: IS_CONSTANT_AST, IS_INDIRECT, IS_PTR, IS_ALIAS_PTR and _IS_ERROR indicate a caller bug and must keep failing loudly.
1 parent 47355da commit 334f9db

1 file changed

Lines changed: 5 additions & 0 deletions

File tree

Zend/zend_operators.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ static zend_never_inline zend_result ZEND_FASTCALL _zendi_try_convert_scalar_to_
355355
}
356356
ZEND_ASSERT(Z_TYPE_P(holder) == IS_LONG || Z_TYPE_P(holder) == IS_DOUBLE);
357357
return SUCCESS;
358+
case IS_UNDEF:
358359
case IS_RESOURCE:
359360
case IS_ARRAY:
360361
return FAILURE;
@@ -556,6 +557,7 @@ ZEND_API void ZEND_FASTCALL convert_to_long(zval *op) /* {{{ */
556557

557558
try_again:
558559
switch (Z_TYPE_P(op)) {
560+
case IS_UNDEF:
559561
case IS_NULL:
560562
case IS_FALSE:
561563
ZVAL_LONG(op, 0);
@@ -617,6 +619,7 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */
617619

618620
try_again:
619621
switch (Z_TYPE_P(op)) {
622+
case IS_UNDEF:
620623
case IS_NULL:
621624
case IS_FALSE:
622625
ZVAL_DOUBLE(op, 0.0);
@@ -689,6 +692,7 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */
689692
case IS_FALSE:
690693
case IS_TRUE:
691694
break;
695+
case IS_UNDEF:
692696
case IS_NULL:
693697
ZVAL_FALSE(op);
694698
break;
@@ -1024,6 +1028,7 @@ ZEND_API double ZEND_FASTCALL zval_get_double_func(const zval *op) /* {{{ */
10241028
{
10251029
try_again:
10261030
switch (Z_TYPE_P(op)) {
1031+
case IS_UNDEF:
10271032
case IS_NULL:
10281033
case IS_FALSE:
10291034
return 0.0;

0 commit comments

Comments
 (0)