]> granicus.if.org Git - php/commitdiff
Fixed bug #55339 (Segfault with allow_call_time_pass_reference = Off)
authorDmitry Stogov <dmitry@php.net>
Tue, 2 Aug 2011 07:38:23 +0000 (07:38 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 2 Aug 2011 07:38:23 +0000 (07:38 +0000)
NEWS
Zend/tests/bug55339.phpt [new file with mode: 0644]
Zend/zend.c

diff --git a/NEWS b/NEWS
index cb3d8a653f23b67208ed97ce8efaa0a3bc2d25cf..d484fdfe2ba187bfe961fbbfa655047d3dfd2dc2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ PHP                                                                        NEWS
     (Scott)
 
 - Core
+  . Fixed bug #55339 (Segfault with allow_call_time_pass_reference = Off).
+    (Dmitry)
   . Fix bug #55295 [NEW]: popen_ex on windows, fixed possible heap overflow
     (Pierre)
   . Fixed bug #50816 (Using class constants in array definition fails).
diff --git a/Zend/tests/bug55339.phpt b/Zend/tests/bug55339.phpt
new file mode 100644 (file)
index 0000000..7d5ab4a
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+Bug #55339 (Segfault with allow_call_time_pass_reference = Off)
+--INI--
+allow_call_time_pass_reference=off
+--FILE--
+<?php
+function error_handler($errno, $errstr, $errfile, $errline) {
+       eval(';');
+}
+
+set_error_handler('error_handler');
+
+eval(<<<'EOF'
+function foo()
+{
+    $array = array();
+    foreach ($array as $key => $value) {
+        bar($key, &$value);
+    }
+}
+
+function bar()
+{
+
+}
+EOF
+);
+
+echo "OK\n";
+--EXPECT--
+OK
index 6861f618bc5a2fbb012394602ebbc5fef2f5af06..bcfedebd96054f8fc8ad448498be32aa88677182 100644 (file)
@@ -958,6 +958,23 @@ ZEND_API int zend_get_configuration_directive(const char *name, uint name_length
 }
 /* }}} */
 
+#define SAVE_STACK(stack) do { \
+               if (CG(stack).top) { \
+                       memcpy(&stack, &CG(stack), sizeof(zend_stack)); \
+                       CG(stack).top = CG(stack).max = 0; \
+                       CG(stack).elements = NULL; \
+               } else { \
+                       stack.top = 0; \
+               } \
+       } while (0)
+
+#define RESTORE_STACK(stack) do { \
+               if (stack.top) { \
+                       zend_stack_destroy(&CG(stack)); \
+                       memcpy(&CG(stack), &stack, sizeof(zend_stack)); \
+               } \
+       } while (0)
+
 ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
 {
        va_list args;
@@ -970,6 +987,14 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
        zval *orig_user_error_handler;
        zend_bool in_compilation;
        zend_class_entry *saved_class_entry;
+       zend_stack bp_stack;
+       zend_stack function_call_stack;
+       zend_stack switch_cond_stack;
+       zend_stack foreach_copy_stack;
+       zend_stack object_stack;
+       zend_stack declare_stack;
+       zend_stack list_stack;
+       zend_stack labels_stack;
        TSRMLS_FETCH();
 
        /* Obtain relevant filename and lineno */
@@ -1097,6 +1122,14 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
                        if (in_compilation) {
                                saved_class_entry = CG(active_class_entry);
                                CG(active_class_entry) = NULL;
+                               SAVE_STACK(bp_stack);
+                               SAVE_STACK(function_call_stack);
+                               SAVE_STACK(switch_cond_stack);
+                               SAVE_STACK(foreach_copy_stack);
+                               SAVE_STACK(object_stack);
+                               SAVE_STACK(declare_stack);
+                               SAVE_STACK(list_stack);
+                               SAVE_STACK(labels_stack);
                        }
 
                        if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC) == SUCCESS) {
@@ -1113,6 +1146,14 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */
 
                        if (in_compilation) {
                                CG(active_class_entry) = saved_class_entry;
+                               RESTORE_STACK(bp_stack);
+                               RESTORE_STACK(function_call_stack);
+                               RESTORE_STACK(switch_cond_stack);
+                               RESTORE_STACK(foreach_copy_stack);
+                               RESTORE_STACK(object_stack);
+                               RESTORE_STACK(declare_stack);
+                               RESTORE_STACK(list_stack);
+                               RESTORE_STACK(labels_stack);
                        }
 
                        if (!EG(user_error_handler)) {