Skip to content

Commit 236eb60

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Respect strict_types during sccp function call evaluation
2 parents 74f4586 + 5b3809e commit 236eb60

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

ext/opcache/Optimizer/sccp.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -900,9 +900,8 @@ static zend_bool can_ct_eval_func_call(zend_string *name, uint32_t num_args, zva
900900
* or just happened to be commonly used with constant operands in WP (need to test other
901901
* applications as well, of course). */
902902
static inline int ct_eval_func_call(
903-
zval *result, zend_string *name, uint32_t num_args, zval **args) {
903+
zend_op_array *op_array, zval *result, zend_string *name, uint32_t num_args, zval **args) {
904904
uint32_t i;
905-
zend_execute_data *execute_data, *prev_execute_data;
906905
zend_function *func = zend_hash_find_ptr(CG(function_table), name);
907906
if (!func || func->type != ZEND_INTERNAL_FUNCTION) {
908907
return FAILURE;
@@ -951,9 +950,20 @@ static inline int ct_eval_func_call(
951950
return FAILURE;
952951
}
953952

953+
zend_execute_data *prev_execute_data = EG(current_execute_data);
954+
zend_execute_data *execute_data, dummy_frame;
955+
zend_op dummy_opline;
956+
957+
/* Add a dummy frame to get the correct strict_types behavior. */
958+
memset(&dummy_frame, 0, sizeof(zend_execute_data));
959+
memset(&dummy_opline, 0, sizeof(zend_op));
960+
dummy_frame.func = (zend_function *) op_array;
961+
dummy_frame.opline = &dummy_opline;
962+
dummy_opline.opcode = ZEND_DO_FCALL;
963+
954964
execute_data = safe_emalloc(num_args, sizeof(zval), ZEND_CALL_FRAME_SLOT * sizeof(zval));
955965
memset(execute_data, 0, sizeof(zend_execute_data));
956-
prev_execute_data = EG(current_execute_data);
966+
execute_data->prev_execute_data = &dummy_frame;
957967
EG(current_execute_data) = execute_data;
958968

959969
EX(func) = func;
@@ -1831,7 +1841,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
18311841
break;
18321842
}
18331843

1834-
if (ct_eval_func_call(&zv, Z_STR_P(name), call->num_args, args) == SUCCESS) {
1844+
if (ct_eval_func_call(scdf->op_array, &zv, Z_STR_P(name), call->num_args, args) == SUCCESS) {
18351845
SET_RESULT(result, &zv);
18361846
zval_ptr_dtor_nogc(&zv);
18371847
break;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Exception thrown during SCCP evaluation, strict types variation
3+
--FILE--
4+
<?php
5+
6+
declare(strict_types=1);
7+
var_dump(str_contains("123", 1));
8+
9+
?>
10+
--EXPECTF--
11+
Fatal error: Uncaught TypeError: str_contains(): Argument #2 ($needle) must be of type string, int given in %s:%d
12+
Stack trace:
13+
#0 %s(%d): str_contains('123', 1)
14+
#1 {main}
15+
thrown in %s on line %d

0 commit comments

Comments
 (0)