From: Nikita Popov Date: Fri, 23 Jun 2017 15:07:44 +0000 (+0200) Subject: Make inference robust against infinite loop X-Git-Tag: php-7.2.0alpha3~44^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4948da178a1e2e0da4bab76fb4b0ff1948ec8d99;p=php Make inference robust against infinite loop Right now, if narrowing occurs on non-debug builds, inference can easily go into an infinite loop. Prevent this, and add a pointer that this should be reported as a bug. --- diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index f572616567..d6a4c273bd 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -1753,8 +1753,11 @@ static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{ } \ } \ if (ssa_var_info[__var].type != __type) { \ - check_type_narrowing(op_array, ssa, worklist, \ - __var, ssa_var_info[__var].type, __type); \ + if (ssa_var_info[__var].type & ~__type) { \ + handle_type_narrowing(op_array, ssa, worklist, \ + __var, ssa_var_info[__var].type, __type); \ + return FAILURE; \ + } \ ssa_var_info[__var].type = __type; \ add_usages(op_array, ssa, worklist, __var); \ } \ @@ -1891,15 +1894,17 @@ static void reset_dependent_vars(const zend_op_array *op_array, zend_ssa *ssa, z #endif } -static void check_type_narrowing(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var, uint32_t old_type, uint32_t new_type) +static void handle_type_narrowing(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var, uint32_t old_type, uint32_t new_type) { - /* if new_type set resets some bits from old_type set - * We have completely recalculate types of some dependent SSA variables - * (this may occurs mainly because of incremental inter-precudure - * type inference) - */ - if (old_type & ~new_type) { - ZEND_ASSERT(0); /* Currently this should never happen */ + if (1) { + /* Right now, this is always a bug */ + zend_error(E_WARNING, "Narrowing occurred during type inference. Please file a bug report on bugs.php.net"); + } else { + /* if new_type set resets some bits from old_type set + * We have completely recalculate types of some dependent SSA variables + * (this may occurs mainly because of incremental inter-precudure + * type inference) + */ reset_dependent_vars(op_array, ssa, worklist, var); } } @@ -2125,7 +2130,7 @@ static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *ar return tmp; } -static void zend_update_type_info(const zend_op_array *op_array, +static int zend_update_type_info(const zend_op_array *op_array, zend_ssa *ssa, const zend_script *script, zend_bitset worklist, @@ -3219,6 +3224,8 @@ unknown_opcode: } break; } + + return SUCCESS; } static uint32_t get_class_entry_rank(zend_class_entry *ce) { @@ -3329,7 +3336,9 @@ int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script } } else if (ssa_vars[j].definition >= 0) { i = ssa_vars[j].definition; - zend_update_type_info(op_array, ssa, script, worklist, i); + if (zend_update_type_info(op_array, ssa, script, worklist, i) == FAILURE) { + return FAILURE; + } } } WHILE_WORKLIST_END(); return SUCCESS;