mirror of
https://github.com/php/php-src.git
synced 2024-12-02 22:34:55 +08:00
Fix free of uninitialized memory in MATCH_ERROR
As suggested by Tyson Andre: https://github.com/php/php-src/pull/5371#issuecomment-657081464 Also fix line number of unhandled match error Closes GH-5841.
This commit is contained in:
parent
c0172aa2bd
commit
1c967df5a0
@ -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"
|
||||
|
@ -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];
|
||||
@ -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]);
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user