Skip to content

Commit 93aabf1

Browse files
committed
Fixed bug #77275
Instead of juggling with this problem during literal compaction, make sure that we always initialize Z_EXTRA for literals, which seems like the more robust solution.
1 parent 59cacdc commit 93aabf1

File tree

5 files changed

+36
-5
lines changed

5 files changed

+36
-5
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ PHP NEWS
3333
- Opcache:
3434
. Fixed bug #77215 (CFG assertion failure on multiple finalizing switch
3535
frees in one block). (Nikita)
36+
. Fixed bug #77275 (OPcache optimization problem for ArrayAccess->offsetGet).
37+
(Nikita)
3638

3739
- PCRE:
3840
. Fixed bug #77193 (Infinite loop in preg_replace_callback). (Anatol)

Zend/zend_compile.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,12 @@ static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */
480480
/* Common part of zend_add_literal and zend_append_individual_literal */
481481
static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */
482482
{
483+
zval *lit = CT_CONSTANT_EX(op_array, literal_position);
483484
if (Z_TYPE_P(zv) == IS_STRING) {
484485
zval_make_interned_string(zv);
485486
}
486-
ZVAL_COPY_VALUE(CT_CONSTANT_EX(op_array, literal_position), zv);
487+
ZVAL_COPY_VALUE(lit, zv);
488+
Z_EXTRA_P(lit) = 0;
487489
}
488490
/* }}} */
489491

@@ -2444,7 +2446,6 @@ static inline void zend_handle_numeric_dim(zend_op *opline, znode *dim_node) /*
24442446
return;
24452447
}
24462448
}
2447-
Z_EXTRA_P(CT_CONSTANT(opline->op2)) = 0;
24482449
}
24492450
/* }}} */
24502451

ext/opcache/Optimizer/compact_literals.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,6 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
378378
} else {
379379
map[i] = j;
380380
ZVAL_LONG(&zv, j);
381-
Z_EXTRA(op_array->literals[i]) = 0; /* allow merging with FETCH_DIM_... */
382381
zend_hash_index_add_new(&hash, Z_LVAL(op_array->literals[i]), &zv);
383382
if (i != j) {
384383
op_array->literals[j] = op_array->literals[i];

ext/opcache/Optimizer/zend_optimizer.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv)
206206
op_array->last_literal++;
207207
op_array->literals = (zval*)erealloc(op_array->literals, op_array->last_literal * sizeof(zval));
208208
ZVAL_COPY_VALUE(&op_array->literals[i], zv);
209+
Z_EXTRA(op_array->literals[i]) = 0;
209210
return i;
210211
}
211212

@@ -533,7 +534,6 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
533534
}
534535
}
535536
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
536-
Z_EXTRA(op_array->literals[opline->op2.constant]) = 0;
537537
} else {
538538
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
539539
}
@@ -562,7 +562,6 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
562562
}
563563
}
564564
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
565-
Z_EXTRA(op_array->literals[opline->op2.constant]) = 0;
566565
break;
567566
case ZEND_ADD_ARRAY_ELEMENT:
568567
case ZEND_INIT_ARRAY:

ext/opcache/tests/bug77275.phpt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Bug #77275: OPcache optimization problem for ArrayAccess->offsetGet(string)
3+
--INI--
4+
opcache.enable_cli=1
5+
opcache.optimization_level=-1
6+
--FILE--
7+
<?php
8+
namespace Foo;
9+
class Bar { public function get() {} }
10+
class Record implements \ArrayAccess {
11+
public function offsetSet($offset, $value) { throw new \Exception; }
12+
public function offsetGet($offset) { var_dump($offset); }
13+
public function offsetExists($offset) { throw new \Exception; }
14+
public function offsetUnset($offset) { throw new \Exception; }
15+
}
16+
class Baz {
17+
public function run() {
18+
$a = pow(1, 2);
19+
$b = new Bar();
20+
$c = new Bar();
21+
$d = new Bar();
22+
$id = $b->get('a', 'b', 'c');
23+
$rec = new Record();
24+
$id = $rec['a'];
25+
}
26+
}
27+
(new Baz())->run();
28+
?>
29+
--EXPECT--
30+
string(1) "a"

0 commit comments

Comments
 (0)