]> granicus.if.org Git - php/commitdiff
Stricter verification of func info against arg info
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 21 Jul 2020 08:42:02 +0000 (10:42 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 21 Jul 2020 09:47:52 +0000 (11:47 +0200)
Make sure they're actually the same up to cases where func info
allows more accurate expressions. There are some awkward edge cases
around true/false/null limitations in union types.

ext/opcache/Optimizer/zend_func_info.c

index 135ff65f5df1994d74aa9c65e66a852f6abbf252..b8c62f54200a1f29f7451719cd22f2aeea242a03 100644 (file)
@@ -932,12 +932,23 @@ uint32_t zend_get_func_info(
                }
 
 #if ZEND_DEBUG
-               /* Check whether the func_info information is a subset of the information we can compute
-                * from the specified return type. */
                if (internal_ret) {
+                       /* Check whether the func_info information is a subset of the information we can
+                        * compute from the specified return type, otherwise it contains redundant types. */
                        if (internal_ret & ~ret) {
                                fprintf(stderr, "Inaccurate func info for %s()\n", ZSTR_VAL(lcname));
                        }
+                       /* If the return type is not mixed, check that the types match exactly if we exclude
+                        * RC and array information. */
+                       uint32_t ret_any = ret & MAY_BE_ANY, internal_ret_any = internal_ret & MAY_BE_ANY;
+                       if (ret_any != MAY_BE_ANY) {
+                               uint32_t diff = internal_ret_any ^ ret_any;
+                               /* Func info may contain "true" types as well as isolated "null" and "false". */
+                               if (diff && !(diff == MAY_BE_FALSE && (ret & MAY_BE_FALSE))
+                                               && (internal_ret_any & ~(MAY_BE_NULL|MAY_BE_FALSE))) {
+                                       fprintf(stderr, "Incorrect func info for %s()\n", ZSTR_VAL(lcname));
+                               }
+                       }
                        return internal_ret;
                }
 #endif