Skip to content

Commit b71b696

Browse files
author
Côme Chilliet
committed
Merge branch 'master' of git.php.net:/php-src
* 'master' of git.php.net:/php-src: Replace ZEND_JIT_TRACE_MAX_EXIT_COUNTERS constant by opcache.jit_max_exit_counters configuration directive Fix use-after-free when nullsafe used with constant LHS
2 parents 08dcb8e + 8a42f35 commit b71b696

File tree

6 files changed

+29
-6
lines changed

6 files changed

+29
-6
lines changed

Zend/tests/nullsafe_operator/029.phpt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Refcount of constant LHS with nullsafe operator
3+
--FILE--
4+
<?php
5+
['']?->a;
6+
?>
7+
--EXPECTF--
8+
Warning: Attempt to read property "a" on array in %s on line %d

Zend/zend_compile.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,6 +2308,9 @@ static void zend_short_circuiting_commit(uint32_t checkpoint, znode *result, zen
23082308
static void zend_emit_jmp_null(znode *obj_node)
23092309
{
23102310
uint32_t jmp_null_opnum = get_next_op_number();
2311+
if (obj_node->op_type == IS_CONST) {
2312+
Z_TRY_ADDREF(obj_node->u.constant);
2313+
}
23112314
zend_emit_op(NULL, ZEND_JMP_NULL, obj_node, NULL);
23122315
zend_stack_push(&CG(short_circuiting_opnums), &jmp_null_opnum);
23132316
}

ext/opcache/jit/zend_jit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3953,6 +3953,9 @@ ZEND_EXT_API void zend_jit_shutdown(void)
39533953
zend_jit_perf_jitdump_close();
39543954
}
39553955
#endif
3956+
if (JIT_G(exit_counters)) {
3957+
free(JIT_G(exit_counters));
3958+
}
39563959
}
39573960

39583961
static void zend_jit_reset_counters(void)

ext/opcache/jit/zend_jit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969

7070
#define ZEND_JIT_TRACE_MAX_LENGTH 1024 /* max length of single trace */
7171
#define ZEND_JIT_TRACE_MAX_EXITS 512 /* max number of side exits per trace */
72-
#define ZEND_JIT_TRACE_MAX_EXIT_COUNTERS 8192 /* max number of side exits for all trace */
7372

7473
#define ZEND_JIT_TRACE_MAX_FUNCS 30 /* max number of different functions in a single trace */
7574
#define ZEND_JIT_TRACE_MAX_CALL_DEPTH 10 /* max depth of inlined calls */
@@ -96,6 +95,7 @@ typedef struct _zend_jit_globals {
9695
double prof_threshold;
9796
zend_long max_root_traces; /* max number of root traces */
9897
zend_long max_side_traces; /* max number of side traces (per root trace) */
98+
zend_long max_exit_counters; /* max total number of side exits for all traces */
9999
zend_long hot_loop;
100100
zend_long hot_func;
101101
zend_long hot_return;
@@ -119,7 +119,7 @@ typedef struct _zend_jit_globals {
119119
uint8_t bad_root_cache_stop[ZEND_JIT_TRACE_BAD_ROOT_SLOTS];
120120
uint32_t bad_root_slot;
121121

122-
uint8_t exit_counters[ZEND_JIT_TRACE_MAX_EXIT_COUNTERS];
122+
uint8_t *exit_counters;
123123
} zend_jit_globals;
124124

125125
#ifdef ZTS

ext/opcache/jit/zend_jit_trace.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ static int zend_jit_trace_startup(void)
6464
memset(&dummy_op_array, 0, sizeof(dummy_op_array));
6565
dummy_op_array.fn_flags = ZEND_ACC_DONE_PASS_TWO;
6666

67+
JIT_G(exit_counters) = calloc(JIT_G(max_exit_counters), 1);
68+
if (JIT_G(exit_counters) == NULL) {
69+
return FAILURE;
70+
}
71+
6772
return SUCCESS;
6873
}
6974

@@ -4579,7 +4584,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
45794584
ZEND_ASSERT(0 && p->stop);
45804585
}
45814586

4582-
if (ZEND_JIT_EXIT_COUNTERS + t->exit_count >= ZEND_JIT_TRACE_MAX_EXIT_COUNTERS) {
4587+
if (ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) {
45834588
goto jit_failure;
45844589
}
45854590

@@ -4788,7 +4793,7 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace
47884793

47894794
ret = ZEND_JIT_TRACE_STOP_COMPILED;
47904795
} else if (t->exit_count >= ZEND_JIT_TRACE_MAX_EXITS ||
4791-
ZEND_JIT_EXIT_COUNTERS + t->exit_count >= ZEND_JIT_TRACE_MAX_EXIT_COUNTERS) {
4796+
ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) {
47924797
if (t->stack_map) {
47934798
efree(t->stack_map);
47944799
t->stack_map = NULL;
@@ -5388,7 +5393,7 @@ static zend_jit_trace_stop zend_jit_compile_side_trace(zend_jit_trace_rec *trace
53885393

53895394
ret = ZEND_JIT_TRACE_STOP_COMPILED;
53905395
} else if (t->exit_count >= ZEND_JIT_TRACE_MAX_EXITS ||
5391-
ZEND_JIT_EXIT_COUNTERS + t->exit_count >= ZEND_JIT_TRACE_MAX_EXIT_COUNTERS) {
5396+
ZEND_JIT_EXIT_COUNTERS + t->exit_count >= JIT_G(max_exit_counters)) {
53925397
if (t->stack_map) {
53935398
efree(t->stack_map);
53945399
t->stack_map = NULL;
@@ -5766,7 +5771,9 @@ static void zend_jit_trace_init_caches(void)
57665771
memset(JIT_G(bad_root_cache_stop), 0, sizeof(JIT_G(bad_root_cache_count)));
57675772
JIT_G(bad_root_slot) = 0;
57685773

5769-
memset(JIT_G(exit_counters), 0, sizeof(JIT_G(exit_counters)));
5774+
if (JIT_G(exit_counters)) {
5775+
memset(JIT_G(exit_counters), 0, JIT_G(max_exit_counters));
5776+
}
57705777
}
57715778

57725779
static void zend_jit_trace_reset_caches(void)

ext/opcache/zend_accelerator_module.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ ZEND_INI_BEGIN()
294294
STD_PHP_INI_ENTRY("opcache.jit_prof_threshold" , "0.005", PHP_INI_ALL, OnUpdateReal, prof_threshold, zend_jit_globals, jit_globals)
295295
STD_PHP_INI_ENTRY("opcache.jit_max_root_traces" , "1024", PHP_INI_SYSTEM, OnUpdateLong, max_root_traces, zend_jit_globals, jit_globals)
296296
STD_PHP_INI_ENTRY("opcache.jit_max_side_traces" , "128", PHP_INI_SYSTEM, OnUpdateLong, max_side_traces, zend_jit_globals, jit_globals)
297+
STD_PHP_INI_ENTRY("opcache.jit_max_exit_counters" , "8192", PHP_INI_SYSTEM, OnUpdateLong, max_exit_counters, zend_jit_globals, jit_globals)
297298
STD_PHP_INI_ENTRY("opcache.jit_hot_loop" , "64", PHP_INI_SYSTEM, OnUpdateCounter, hot_loop, zend_jit_globals, jit_globals)
298299
STD_PHP_INI_ENTRY("opcache.jit_hot_func" , "127", PHP_INI_SYSTEM, OnUpdateCounter, hot_func, zend_jit_globals, jit_globals)
299300
STD_PHP_INI_ENTRY("opcache.jit_hot_return" , "8", PHP_INI_SYSTEM, OnUpdateCounter, hot_return, zend_jit_globals, jit_globals)
@@ -783,6 +784,7 @@ ZEND_FUNCTION(opcache_get_configuration)
783784
add_assoc_long(&directives, "opcache.jit_hot_loop", JIT_G(hot_loop));
784785
add_assoc_long(&directives, "opcache.jit_hot_return", JIT_G(hot_return));
785786
add_assoc_long(&directives, "opcache.jit_hot_side_exit", JIT_G(hot_side_exit));
787+
add_assoc_long(&directives, "opcache.jit_max_exit_counters", JIT_G(max_exit_counters));
786788
add_assoc_long(&directives, "opcache.jit_max_loops_unroll", JIT_G(max_loops_unroll));
787789
add_assoc_long(&directives, "opcache.jit_max_polymorphic_calls", JIT_G(max_polymorphic_calls));
788790
add_assoc_long(&directives, "opcache.jit_max_recursive_calls", JIT_G(max_recursive_calls));

0 commit comments

Comments
 (0)