Skip to content

Commit a3b148e

Browse files
committed
Fix GH-14361: Deep recursion in zend_cfg.c causes segfault
Changes the CFG reachability algorithm to use iteration instead of recursion. Closes GH-14432.
1 parent 2a02d35 commit a3b148e

File tree

2 files changed

+16
-15
lines changed

2 files changed

+16
-15
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ PHP NEWS
121121
64bit archs. (Arnaud)
122122
. Fixed bug GH-13834 (Applying non-zero offset 36 to null pointer in
123123
zend_jit.c). (nielsdos)
124+
. Fixed bug GH-14361 (Deep recursion in zend_cfg.c causes segfault).
125+
(nielsdos)
124126

125127
- OpenSSL:
126128
. Fixed bug #80269 (OpenSSL sets Subject wrong with extraattribs parameter).

Zend/Optimizer/zend_cfg.c

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,20 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc
2828
{
2929
zend_basic_block *blocks = cfg->blocks;
3030

31-
while (1) {
31+
zend_worklist work;
32+
ALLOCA_FLAG(list_use_heap)
33+
ZEND_WORKLIST_ALLOCA(&work, cfg->blocks_count, list_use_heap);
34+
35+
zend_worklist_push(&work, b - cfg->blocks);
36+
37+
while (zend_worklist_len(&work)) {
3238
int i;
39+
b = cfg->blocks + zend_worklist_pop(&work);
3340

3441
b->flags |= ZEND_BB_REACHABLE;
3542
if (b->successors_count == 0) {
3643
b->flags |= ZEND_BB_EXIT;
37-
return;
44+
continue;
3845
}
3946

4047
for (i = 0; i < b->successors_count; i++) {
@@ -86,22 +93,14 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc
8693
succ->flags |= ZEND_BB_FOLLOW;
8794
}
8895

89-
if (i == b->successors_count - 1) {
90-
/* Tail call optimization */
91-
if (succ->flags & ZEND_BB_REACHABLE) {
92-
return;
93-
}
94-
95-
b = succ;
96-
break;
97-
} else {
98-
/* Recursively check reachability */
99-
if (!(succ->flags & ZEND_BB_REACHABLE)) {
100-
zend_mark_reachable(opcodes, cfg, succ);
101-
}
96+
/* Check reachability of successor */
97+
if (!(succ->flags & ZEND_BB_REACHABLE)) {
98+
zend_worklist_push(&work, succ - cfg->blocks);
10299
}
103100
}
104101
}
102+
103+
ZEND_WORKLIST_FREE_ALLOCA(&work, list_use_heap);
105104
}
106105
/* }}} */
107106

0 commit comments

Comments
 (0)