Skip to content

Commit

Permalink
Fix free of uninitialized memory in MATCH_ERROR
Browse files Browse the repository at this point in the history
As suggested by Tyson Andre:
#5371 (comment)

Also fix line number of unhandled match error

Closes GH-5841.
  • Loading branch information
iluuu1994 committed Jul 12, 2020
1 parent c0172aa commit 1c967df
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 27 deletions.
6 changes: 3 additions & 3 deletions Zend/tests/match/037.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ var_dump(match(3) {

?>
--EXPECTF--
string(%d) "UnhandledMatchError: Unhandled match value of type bool in %s037.php:5
string(%d) "UnhandledMatchError: Unhandled match value of type bool in %s037.php:4
Stack trace:
#0 {main}"
string(%d) "UnhandledMatchError: Unhandled match value of type int in %s037.php:13
string(%d) "UnhandledMatchError: Unhandled match value of type int in %s037.php:12
Stack trace:
#0 {main}"
string(%d) "UnhandledMatchError: Unhandled match value of type string in %s037.php:21
string(%d) "UnhandledMatchError: Unhandled match value of type string in %s037.php:20
Stack trace:
#0 {main}"
string(3) "foo"
Expand Down
34 changes: 18 additions & 16 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -5297,6 +5297,24 @@ void zend_compile_match(znode *result, zend_ast *ast)
uint32_t cond_count = 0;
uint32_t *jmp_end_opnums = safe_emalloc(sizeof(uint32_t), arms->children, 0);

// The generated default arm is emitted first to avoid live range issues where the tmpvar
// for the arm result is freed even though it has not been initialized yet.
if (!has_default_arm) {
if (!uses_jumptable) {
zend_update_jump_target_to_next(opnum_default_jmp);
}

if (jumptable) {
zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
opline->extended_value = get_next_op_number();
}

zend_op *opline = zend_emit_op(NULL, ZEND_MATCH_ERROR, &expr_node, NULL);
if (opline->op1_type == IS_CONST) {
Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
}
}

for (uint32_t i = 0; i < arms->children; ++i) {
zend_ast *arm_ast = arms->child[i];
zend_ast *body_ast = arm_ast->child[1];
Expand Down Expand Up @@ -5358,22 +5376,6 @@ void zend_compile_match(znode *result, zend_ast *ast)
ZVAL_NULL(&result->u.constant);
}

if (!has_default_arm) {
if (!uses_jumptable) {
zend_update_jump_target_to_next(opnum_default_jmp);
}

if (jumptable) {
zend_op *opline = &CG(active_op_array)->opcodes[opnum_match];
opline->extended_value = get_next_op_number();
}

zend_op *opline = zend_emit_op(NULL, ZEND_MATCH_ERROR, &expr_node, NULL);
if (opline->op1_type == IS_CONST) {
Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
}
}

for (uint32_t i = 0; i < arms->children; ++i) {
zend_update_jump_target_to_next(jmp_end_opnums[i]);
}
Expand Down
16 changes: 8 additions & 8 deletions ext/opcache/tests/match/001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ test:
; (after optimizer)
; %s
0000 CV0($char) = RECV 1
0001 MATCH CV0($char) "a": 0002, "b": 0003, "c": 0003, "d": 0004, "e": 0005, "f": 0005, "g": 0006, "h": 0007, "i": 0007, default: 0008
0002 RETURN string("a")
0003 RETURN string("b, c")
0004 RETURN string("d")
0005 RETURN string("e, f")
0006 RETURN string("g")
0007 RETURN string("h, i")
0008 MATCH_ERROR CV0($char)
0001 MATCH CV0($char) "a": 0003, "b": 0004, "c": 0004, "d": 0005, "e": 0006, "f": 0006, "g": 0007, "h": 0008, "i": 0008, default: 0002
0002 MATCH_ERROR CV0($char)
0003 RETURN string("a")
0004 RETURN string("b, c")
0005 RETURN string("d")
0006 RETURN string("e, f")
0007 RETURN string("g")
0008 RETURN string("h, i")
string(1) "a"
string(4) "b, c"
string(4) "b, c"
Expand Down

0 comments on commit 1c967df

Please sign in to comment.