Skip to content

Commit a697083

Browse files
authored
Extended map_ptr before copying class table (#9188)
Fixes GH-9164
1 parent 1478278 commit a697083

File tree

3 files changed

+58
-11
lines changed

3 files changed

+58
-11
lines changed

Zend/zend_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,7 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
743743

744744
#define ZSTR_SET_CE_CACHE_EX(s, ce, validate) do { \
745745
if (!(validate) || ZSTR_VALID_CE_CACHE(s)) { \
746+
ZEND_ASSERT((validate) || ZSTR_VALID_CE_CACHE(s)); \
746747
SET_CE_CACHE(GC_REFCOUNT(s), ce); \
747748
} \
748749
} while (0)

ext/opcache/tests/gh9164.phpt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
Bug GH-9164: Segfault in zend_accel_class_hash_copy
3+
--EXTENSIONS--
4+
opcache
5+
pcntl
6+
--INI--
7+
opcache.enable_cli=1
8+
--FILE--
9+
<?php
10+
11+
$incfile = __DIR__.'/gh9164.inc';
12+
13+
// Generate enough classes so that the out of bound access will cause a crash
14+
// without relying on assertion
15+
$fd = fopen($incfile, 'w');
16+
fwrite($fd, "<?php\n");
17+
for ($i = 0; $i < 4096; $i++) {
18+
fprintf($fd, "class FooBar%04d {}\n", $i);
19+
}
20+
fclose($fd);
21+
22+
// Ensure cacheability
23+
touch($incfile, time() - 3600);
24+
25+
$pid = pcntl_fork();
26+
if ($pid == 0) {
27+
// Child: Declare classes to allocate CE cache slots.
28+
require $incfile;
29+
} else if ($pid > 0) {
30+
pcntl_wait($status);
31+
// Ensure that file has been cached. If not, this is testing nothing anymore.
32+
if (!isset(opcache_get_status()['scripts'][$incfile])) {
33+
print "File not cached\n";
34+
}
35+
// Populates local cache
36+
require $incfile;
37+
var_dump(new FooBar4095);
38+
unlink($incfile);
39+
} else {
40+
echo "pcntl_fork() failed\n";
41+
}
42+
43+
?>
44+
--EXPECTF--
45+
object(FooBar4095)#%d (0) {
46+
}

ext/opcache/zend_accelerator_util_funcs.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -347,15 +347,11 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
347347
op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
348348
*op_array = persistent_script->script.main_op_array;
349349

350-
if (zend_hash_num_elements(&persistent_script->script.function_table) > 0) {
351-
zend_accel_function_hash_copy(CG(function_table), &persistent_script->script.function_table);
352-
}
353-
354-
if (zend_hash_num_elements(&persistent_script->script.class_table) > 0) {
355-
zend_accel_class_hash_copy(CG(class_table), &persistent_script->script.class_table);
356-
}
357-
358350
if (EXPECTED(from_shared_memory)) {
351+
if (ZCSG(map_ptr_last) > CG(map_ptr_last)) {
352+
zend_map_ptr_extend(ZCSG(map_ptr_last));
353+
}
354+
359355
/* Register __COMPILER_HALT_OFFSET__ constant */
360356
if (persistent_script->compiler_halt_offset != 0 &&
361357
persistent_script->script.filename) {
@@ -368,10 +364,14 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
368364
}
369365
zend_string_release_ex(name, 0);
370366
}
367+
}
371368

372-
if (ZCSG(map_ptr_last) > CG(map_ptr_last)) {
373-
zend_map_ptr_extend(ZCSG(map_ptr_last));
374-
}
369+
if (zend_hash_num_elements(&persistent_script->script.function_table) > 0) {
370+
zend_accel_function_hash_copy(CG(function_table), &persistent_script->script.function_table);
371+
}
372+
373+
if (zend_hash_num_elements(&persistent_script->script.class_table) > 0) {
374+
zend_accel_class_hash_copy(CG(class_table), &persistent_script->script.class_table);
375375
}
376376

377377
if (persistent_script->num_early_bindings) {

0 commit comments

Comments
 (0)