]> granicus.if.org Git - php/commitdiff
Fixed bug #71300 (Segfault in zend_fetch_string_offset)
authorXinchen Hui <laruence@gmail.com>
Thu, 7 Jan 2016 15:05:17 +0000 (07:05 -0800)
committerXinchen Hui <laruence@gmail.com>
Thu, 7 Jan 2016 15:05:17 +0000 (07:05 -0800)
NEWS
Zend/tests/bug71300.phpt [new file with mode: 0644]
Zend/zend_compile.c

diff --git a/NEWS b/NEWS
index d33a8fdc4f179902612f78d952a256a5e688167c..b5f5a32b46e04170267f1cd7a3dee5a12cd62254 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ PHP                                                                        NEWS
 ?? ??? 2016 PHP 7.0.3
 
 - Core:
+  . Fixed bug #71300 (Segfault in zend_fetch_string_offset). (Laruence)
   . Fixed bug #71221 (Null pointer deref (segfault) in get_defined_vars via
     ob_start). (hugh at allthethings dot co dot nz)
   . Fixed bug #71201 (round() segfault on 64-bit builds). (Anatol)
diff --git a/Zend/tests/bug71300.phpt b/Zend/tests/bug71300.phpt
new file mode 100644 (file)
index 0000000..3589c47
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+Bug #71300 (Segfault in zend_fetch_string_offset)
+--FILE--
+<?php
+function test1() {
+       for ($n = 'a'; $n < 'g'; $n++) {
+               $$n = 1;
+       }
+       $$n = $$n[++$n] = "test";
+       return $$n;
+}
+
+var_dump(test1());
+
+function test2() {
+    /* See #71303 for why not using for loop here */
+       $n = "a";
+       $$n .= $$n[++$n] = "test";
+       return $$n;
+}
+
+var_dump(test2());
+?>
+--EXPECTF--
+string(4) "test"
+
+Notice: Array to string conversion in %sbug71300.php on line %d
+string(9) "Arraytest"
index 44ae08d409ef627ec47c71caa730de8b11a25020..1c30b98a9f54b01b08df7fffe6745c8cb1cfcf2b 100644 (file)
@@ -1999,7 +1999,7 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
        zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
        uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
 
-       ZEND_ASSERT(count > offset);
+       ZEND_ASSERT(count >= offset);
        for (i = offset; i < count; ++i) {
                opline = get_next_op(CG(active_op_array));
                memcpy(opline, &oplines[i], sizeof(zend_op));
@@ -2535,8 +2535,10 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
        switch (var_ast->kind) {
                case ZEND_AST_VAR:
                case ZEND_AST_STATIC_PROP:
-                       zend_compile_var(&var_node, var_ast, BP_VAR_W);
+                       offset = zend_delayed_compile_begin();
+                       zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W);
                        zend_compile_expr(&expr_node, expr_ast);
+                       zend_delayed_compile_end(offset);
                        zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node);
                        return;
                case ZEND_AST_DIM:
@@ -2634,8 +2636,10 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
        switch (var_ast->kind) {
                case ZEND_AST_VAR:
                case ZEND_AST_STATIC_PROP:
-                       zend_compile_var(&var_node, var_ast, BP_VAR_RW);
+                       offset = zend_delayed_compile_begin();
+                       zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW);
                        zend_compile_expr(&expr_node, expr_ast);
+                       zend_delayed_compile_end(offset);
                        zend_emit_op(result, opcode, &var_node, &expr_node);
                        return;
                case ZEND_AST_DIM: