]> granicus.if.org Git - php/commitdiff
Handle "non well formed" exception during ZPP
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 8 Oct 2019 14:53:23 +0000 (16:53 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 8 Oct 2019 15:17:49 +0000 (17:17 +0200)
Previously if the "non well formed" notice was converted into an
exception we'd still end up executing the function.

Also drop the now unnecessary EG(exception) checks in the engine.

Additionally remote a bogus exception in zend_is_callable: It
should only be writing to error, but not directly throwing.

Zend/tests/exception_017.phpt
Zend/tests/non_well_formed_param_exception.phpt [new file with mode: 0644]
Zend/zend_API.c
Zend/zend_execute.c
Zend/zend_operators.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index f980b297fbd6bc48ab7386bcb3d0acf59b95775f..8d87ec6ee95d240611eaffa8c4ce5d307dcedb52 100644 (file)
@@ -30,8 +30,7 @@ C::foo();
 --EXPECTF--
 Exception: Cannot call abstract method C::foo() in %sexception_017.php on line %d
 
-Exception: Argument 1 passed to foo() must be callable, string given, called in %sexception_017.php on line %d
-Exception: Cannot call abstract method C::foo()
+Exception: Argument 1 passed to foo() must be callable, string given, called in %s on line %d
 
 Fatal error: Uncaught Error: Cannot call abstract method C::foo() in %sexception_017.php:%d
 Stack trace:
diff --git a/Zend/tests/non_well_formed_param_exception.phpt b/Zend/tests/non_well_formed_param_exception.phpt
new file mode 100644 (file)
index 0000000..d688375
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+A "non well formed" notice converted to exception should result in a ZPP failure
+--FILE--
+<?php
+
+set_error_handler(function($_, $msg) {
+    throw new Exception($msg);
+}, E_NOTICE);
+
+try {
+    wordwrap("foo", "123foo", "");
+} catch (Exception $e) {
+    echo $e, "\n";
+}
+
+?>
+--EXPECTF--
+Exception: A non well formed numeric value encountered in %s:%d
+Stack trace:
+#0 [internal function]: {closure}(%s)
+#1 %s(%d): wordwrap('foo', '123foo', '')
+#2 {main}
index 5be9d94dee3160cfbf42ebbea4560057010114e4..3fef3733f72b17c484b9e7148e148dd430a71f5a 100644 (file)
@@ -438,6 +438,9 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest)
                                return 0;
                        }
                }
+               if (UNEXPECTED(EG(exception))) {
+                       return 0;
+               }
        } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
                *dest = 0;
        } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
@@ -479,6 +482,9 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *de
                                return 0;
                        }
                }
+               if (UNEXPECTED(EG(exception))) {
+                       return 0;
+               }
        } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
                *dest = 0;
        } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
@@ -514,6 +520,9 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest) /
                                return 0;
                        }
                }
+               if (UNEXPECTED(EG(exception))) {
+                       return 0;
+               }
        } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
                *dest = 0.0;
        } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
@@ -3163,12 +3172,9 @@ get_function_via_handler:
        if (retval) {
                if (fcc->calling_scope && !call_via_handler) {
                        if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) {
+                               retval = 0;
                                if (error) {
                                        zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
-                                       retval = 0;
-                               } else {
-                                       zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
-                                       retval = 0;
                                }
                        } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
                                int severity;
index 15f3ee792a22848a68c2aeaa2fbceaa8b4bce86e..015ee8990ff9c4d4468f78572f8c60f63eb6a79e 100644 (file)
@@ -792,6 +792,12 @@ static ZEND_COLD void zend_verify_arg_error(
        const char *fname, *fsep, *fclass;
        const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
 
+       if (EG(exception)) {
+               /* The type verification itself might have already thrown an exception
+                * through a promoted warning. */
+               return;
+       }
+
        if (value) {
                zend_verify_type_error_common(
                        zf, arg_info, ce, value,
index 840ee75a413101fec5568df4bbbbaa0d4abc17fa..7c0c5691646e9bbc4f6424f179a054ed8dbe2570 100644 (file)
@@ -3131,6 +3131,9 @@ process_double:
                }
                if (allow_errors == -1) {
                        zend_error(E_NOTICE, "A non well formed numeric value encountered");
+                       if (EG(exception)) {
+                               return 0;
+                       }
                }
        }
 
index 7c102073a3b501f84f460ba22d2312bfcd1e4fd0..649b07d36ebc27ed9fb389c327f0790d8335e55c 100644 (file)
@@ -5209,7 +5209,7 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED|CACHE_SLOT)
                zval *param = EX_VAR(opline->result.var);
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)) || EG(exception))) {
+               if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) {
                        HANDLE_EXCEPTION();
                }
        }
@@ -5257,7 +5257,7 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT)
                zval *default_value = RT_CONSTANT(opline, opline->op2);
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)) || EG(exception))) {
+               if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) {
                        HANDLE_EXCEPTION();
                }
        }
index 4cd21c0e61f58f33bd5833085d5a711839f4cebd..b4a59dff0e7278b5951242f68be5ae9767e6980e 100644 (file)
@@ -3060,7 +3060,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON
                zval *default_value = RT_CONSTANT(opline, opline->op2);
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)) || EG(exception))) {
+               if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) {
                        HANDLE_EXCEPTION();
                }
        }
@@ -3139,7 +3139,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_H
                zval *param = EX_VAR(opline->result.var);
 
                SAVE_OPLINE();
-               if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)) || EG(exception))) {
+               if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) {
                        HANDLE_EXCEPTION();
                }
        }