Skip to content

Commit aff1155

Browse files
committed
JIT: Fix exception handling when next array element is already occupied
Fixes oss-fuzz #41408
1 parent 816aa20 commit aff1155

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed

ext/opcache/Optimizer/dce.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,10 @@ static inline zend_bool may_break_varargs(const zend_op_array *op_array, const z
491491
return 0;
492492
}
493493

494+
static inline zend_bool may_throw_dce_exception(const zend_op *opline) {
495+
return opline->opcode == ZEND_ADD_ARRAY_ELEMENT && opline->op2_type == IS_UNUSED;
496+
}
497+
494498
int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reorder_dtor_effects) {
495499
int i;
496500
zend_ssa_phi *phi;
@@ -557,7 +561,8 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
557561
add_operands_to_worklists(&ctx, &op_array->opcodes[op_data], &ssa->ops[op_data], ssa, 0);
558562
}
559563
} else if (may_have_side_effects(op_array, ssa, &op_array->opcodes[i], &ssa->ops[i], ctx.reorder_dtor_effects)
560-
|| zend_may_throw(&op_array->opcodes[i], &ssa->ops[i], op_array, ssa)
564+
|| (zend_may_throw(&op_array->opcodes[i], &ssa->ops[i], op_array, ssa)
565+
&& !may_throw_dce_exception(&op_array->opcodes[i]))
561566
|| (has_varargs && may_break_varargs(op_array, ssa, &ssa->ops[i]))) {
562567
if (op_array->opcodes[i].opcode == ZEND_NEW
563568
&& op_array->opcodes[i+1].opcode == ZEND_DO_FCALL

ext/opcache/Optimizer/sccp.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,6 +2316,12 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
23162316
return 0;
23172317
}
23182318
break;
2319+
case ZEND_INIT_ARRAY:
2320+
case ZEND_ADD_ARRAY_ELEMENT:
2321+
if (opline->op2_type == IS_UNUSED) {
2322+
return 0;
2323+
}
2324+
/* break missing intentionally */
23192325
default:
23202326
if (zend_may_throw(opline, ssa_op, op_array, ssa)) {
23212327
return 0;

ext/opcache/Optimizer/zend_inference.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4628,8 +4628,9 @@ int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const ze
46284628
case ZEND_ROPE_END:
46294629
return t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT);
46304630
case ZEND_INIT_ARRAY:
4631-
case ZEND_ADD_ARRAY_ELEMENT:
46324631
return (opline->op2_type != IS_UNUSED) && (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
4632+
case ZEND_ADD_ARRAY_ELEMENT:
4633+
return (opline->op2_type == IS_UNUSED) || (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
46334634
case ZEND_STRLEN:
46344635
return (t1 & MAY_BE_ANY) != MAY_BE_STRING;
46354636
case ZEND_COUNT:
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Occupied next element
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit_buffer_size=1M
8+
--FILE--
9+
<?php
10+
$float = 100000000000000000000000000000000000000;
11+
$string_float= PHP_INT_MAX;
12+
$a = [$float => 'a', $string_float => 'b', 'c', 'd'];
13+
?>
14+
--EXPECTF--
15+
Fatal error: Uncaught Error: Cannot add element to the array as the next element is already occupied in %sarray_elem_002.php:4
16+
Stack trace:
17+
#0 {main}
18+
thrown in %sarray_elem_002.php on line 4

0 commit comments

Comments
 (0)