]> granicus.if.org Git - php/commitdiff
Fix free of uninitialized memory in MATCH_ERROR
authorIlija Tovilo <ilija.tovilo@me.com>
Sat, 11 Jul 2020 16:46:51 +0000 (18:46 +0200)
committerIlija Tovilo <ilija.tovilo@me.com>
Sun, 12 Jul 2020 11:33:36 +0000 (13:33 +0200)
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.

Zend/tests/match/037.phpt
Zend/zend_compile.c
ext/opcache/tests/match/001.phpt

index abd5dcfdc1855cda5bc00ec2b01d0302f571f6ba..d3591fbfcba264c7b8fbee7a1a80a19441c51e80 100644 (file)
@@ -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"
index cfe058b72be301775ee61483be781b7050d86b7a..118c9681d22d8d1e13c8abf1056f686e8b607c92 100644 (file)
@@ -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]);
        }
index 0f6c4f07075c86c7648e1b0d1a773d79b2153b49..7963733594fa8c4b97367a0915d63b2d2e295538 100644 (file)
@@ -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"