Skip to content

Commit 4354ce4

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 4354ce4

File tree

3 files changed

+74
-18
lines changed

3 files changed

+74
-18
lines changed

Zend/zend_vm_def.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9638,9 +9638,9 @@ 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)) {
9643+
ZVAL_NULL(result);
96449644
FREE_OP1();
96459645
HANDLE_EXCEPTION();
96469646
}
@@ -9651,8 +9651,11 @@ ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED, SPEC(OBSERVER))
96519651
} else
96529652
#endif
96539653
{
9654+
zval tmp_result;
9655+
ZVAL_NULL(&tmp_result);
96549656
zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline);
9655-
function(result, arg1);
9657+
function(&tmp_result, arg1);
9658+
ZVAL_COPY_VALUE(result, &tmp_result);
96569659
}
96579660
FREE_OP1();
96589661
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -9664,10 +9667,10 @@ ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
96649667
SAVE_OPLINE();
96659668

96669669
zval *result = EX_VAR(opline->result.var);
9667-
ZVAL_NULL(result);
96689670
zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
96699671
zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
96709672
if (EG(exception)) {
9673+
ZVAL_NULL(result);
96719674
FREE_OP1();
96729675
FREE_OP2();
96739676
HANDLE_EXCEPTION();
@@ -9679,8 +9682,11 @@ ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
96799682
} else
96809683
#endif
96819684
{
9685+
zval tmp_result;
9686+
ZVAL_NULL(&tmp_result);
96829687
zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline);
9683-
function(result, arg1, arg2);
9688+
function(&tmp_result, arg1, arg2);
9689+
ZVAL_COPY_VALUE(result, &tmp_result);
96849690
}
96859691

96869692
FREE_OP1();
@@ -9698,11 +9704,11 @@ ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
96989704
SAVE_OPLINE();
96999705

97009706
zval *result = EX_VAR(opline->result.var);
9701-
ZVAL_NULL(result);
97029707
zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
97039708
zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
97049709
zval *arg3 = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R);
97059710
if (EG(exception)) {
9711+
ZVAL_NULL(result);
97069712
FREE_OP1();
97079713
FREE_OP2();
97089714
FREE_OP_DATA();
@@ -9715,8 +9721,11 @@ ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
97159721
} else
97169722
#endif
97179723
{
9724+
zval tmp_result;
9725+
ZVAL_NULL(&tmp_result);
97189726
zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline);
9719-
function(result, arg1, arg2, arg3);
9727+
function(&tmp_result, arg1, arg2, arg3);
9728+
ZVAL_COPY_VALUE(result, &tmp_result);
97209729
}
97219730

97229731
FREE_OP1();

Zend/zend_vm_execute.h

Lines changed: 30 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)