Skip to content

Commit bdb8a03

Browse files
committed
Fix GH-14873: PHP 8.4 min function fails on typed integer
The DFA pass may cause the op1 and result argument to be equal to each other. In the VM we always use ZVAL_NULL(result) first, which will also destroy the first argument. Use a temporary result to fix the issue.
1 parent 0b3c506 commit bdb8a03

File tree

3 files changed

+65
-18
lines changed

3 files changed

+65
-18
lines changed

Zend/zend_vm_def.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9638,7 +9638,6 @@ ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED, SPEC(OBSERVER))
96389638
SAVE_OPLINE();
96399639

96409640
zval *result = EX_VAR(opline->result.var);
9641-
ZVAL_NULL(result);
96429641
zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
96439642
if (EG(exception)) {
96449643
FREE_OP1();
@@ -9651,8 +9650,11 @@ ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED, SPEC(OBSERVER))
96519650
} else
96529651
#endif
96539652
{
9653+
zval tmp_result;
9654+
ZVAL_NULL(&tmp_result);
96549655
zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline);
9655-
function(result, arg1);
9656+
function(&tmp_result, arg1);
9657+
ZVAL_COPY_VALUE(result, &tmp_result);
96569658
}
96579659
FREE_OP1();
96589660
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -9664,7 +9666,6 @@ ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
96649666
SAVE_OPLINE();
96659667

96669668
zval *result = EX_VAR(opline->result.var);
9667-
ZVAL_NULL(result);
96689669
zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
96699670
zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
96709671
if (EG(exception)) {
@@ -9679,8 +9680,11 @@ ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
96799680
} else
96809681
#endif
96819682
{
9683+
zval tmp_result;
9684+
ZVAL_NULL(&tmp_result);
96829685
zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline);
9683-
function(result, arg1, arg2);
9686+
function(&tmp_result, arg1, arg2);
9687+
ZVAL_COPY_VALUE(result, &tmp_result);
96849688
}
96859689

96869690
FREE_OP1();
@@ -9698,7 +9702,6 @@ ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
96989702
SAVE_OPLINE();
96999703

97009704
zval *result = EX_VAR(opline->result.var);
9701-
ZVAL_NULL(result);
97029705
zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
97039706
zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
97049707
zval *arg3 = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R);
@@ -9715,8 +9718,11 @@ ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
97159718
} else
97169719
#endif
97179720
{
9721+
zval tmp_result;
9722+
ZVAL_NULL(&tmp_result);
97189723
zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline);
9719-
function(result, arg1, arg2, arg3);
9724+
function(&tmp_result, arg1, arg2, arg3);
9725+
ZVAL_COPY_VALUE(result, &tmp_result);
97209726
}
97219727

97229728
FREE_OP1();

Zend/zend_vm_execute.h

Lines changed: 24 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/tests/array/gh14873.phpt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
GH-14873 (PHP 8.4 min function fails on typed integer)
3+
--FILE--
4+
<?php
5+
6+
function testTrim1(string $value): string {
7+
$value = trim($value);
8+
return $value;
9+
}
10+
11+
function testMin2(int $value): int {
12+
$value = min($value, 100);
13+
return $value;
14+
}
15+
16+
function testMin3(int $value): int {
17+
$value = min($value, 100, 200);
18+
return $value;
19+
}
20+
21+
var_dump(testTrim1(" boo "));
22+
var_dump(testMin2(5));
23+
var_dump(testMin3(5));
24+
25+
?>
26+
--EXPECT--
27+
string(3) "boo"
28+
int(5)
29+
int(5)

0 commit comments

Comments
 (0)