]> granicus.if.org Git - php/commitdiff
Fix handling of sccp exceptions
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 27 Nov 2020 16:43:24 +0000 (17:43 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 27 Nov 2020 16:44:30 +0000 (17:44 +0100)
We should clear the exception *before* we destroy the execute_data.
Add a variation of the test that indirects through another file,
and would crash otherwise.

ext/opcache/Optimizer/sccp.c
ext/opcache/tests/opt/sccp_exception2.inc [new file with mode: 0644]
ext/opcache/tests/opt/sccp_exception2.phpt [new file with mode: 0644]

index 1c4330717ba0cf0843fab8f51f644f213722c367..9f122296f5d9c8a74b33edbf8ce3d95d404380e3 100644 (file)
@@ -1046,16 +1046,17 @@ static inline int ct_eval_func_call(
        for (i = 0; i < num_args; i++) {
                zval_ptr_dtor_nogc(EX_VAR_NUM(i));
        }
-       efree(execute_data);
-       EG(current_execute_data) = prev_execute_data;
 
+       int retval = SUCCESS;
        if (EG(exception)) {
                zval_ptr_dtor(result);
                zend_clear_exception();
-               return FAILURE;
+               retval = FAILURE;
        }
 
-       return SUCCESS;
+       efree(execute_data);
+       EG(current_execute_data) = prev_execute_data;
+       return retval;
 }
 
 #define SET_RESULT(op, zv) do { \
diff --git a/ext/opcache/tests/opt/sccp_exception2.inc b/ext/opcache/tests/opt/sccp_exception2.inc
new file mode 100644 (file)
index 0000000..896d89d
--- /dev/null
@@ -0,0 +1,2 @@
+<?php
+var_dump(version_compare('1.2', '2.1', '??'));
diff --git a/ext/opcache/tests/opt/sccp_exception2.phpt b/ext/opcache/tests/opt/sccp_exception2.phpt
new file mode 100644 (file)
index 0000000..1485de5
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+Exception thrown during SCCP evaluation, separate file variation
+--FILE--
+<?php
+require __DIR__ . '/sccp_exception2.inc';
+?>
+--EXPECTF--
+Fatal error: Uncaught ValueError: version_compare(): Argument #3 ($operator) must be a valid comparison operator in %s:%d
+Stack trace:
+#0 %s(%d): version_compare('1.2', '2.1', '??')
+#1 %s(%d): require('/home/nikic/php...')
+#2 {main}
+  thrown in %s on line %d