diff options
Diffstat (limited to 'ext/opcache/Optimizer/zend_inference.c')
-rw-r--r-- | ext/opcache/Optimizer/zend_inference.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index aeb30c8ec5..9f930a1ab6 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -157,6 +157,17 @@ } \ } while (0) +static inline zend_bool add_will_overflow(zend_long a, zend_long b) { + return (b > 0 && a > ZEND_LONG_MAX - b) + || (b < 0 && a < ZEND_LONG_MIN - b); +} +#if 0 +static inline zend_bool sub_will_overflow(zend_long a, zend_long b) { + return (b > 0 && a < ZEND_LONG_MIN + b) + || (b < 0 && a > ZEND_LONG_MAX + b); +} +#endif + static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, int *dfs, int *root, zend_worklist_stack *stack) /* {{{ */ { #ifdef SYM_RANGE @@ -826,7 +837,9 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int #ifdef SYM_RANGE } else if (narrowing && ssa->var_info[constraint->min_ssa_var].has_range) { tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow && tmp->underflow; - tmp->min = MAX(ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min, tmp->min); + if (!add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) { + tmp->min = MAX(ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min, tmp->min); + } #endif } if (constraint->max_ssa_var < 0) { @@ -834,7 +847,9 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int tmp->overflow = constraint->range.overflow && tmp->overflow; #ifdef SYM_RANGE } else if (narrowing && ssa->var_info[constraint->max_ssa_var].has_range) { - tmp->max = MIN(ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max, tmp->max); + if (!add_will_overflow(ssa->var_info[constraint->max_ssa_var].range.max, constraint->range.max)) { + tmp->max = MIN(ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max, tmp->max); + } tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow && tmp->overflow; #endif } @@ -844,8 +859,13 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int tmp->min = constraint->range.min; #ifdef SYM_RANGE } else if (narrowing && ssa->var_info[constraint->min_ssa_var].has_range) { - tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow; - tmp->min = ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min; + if (add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) { + tmp->underflow = 1; + tmp->min = ZEND_LONG_MIN; + } else { + tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow; + tmp->min = ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min; + } #endif } else { tmp->underflow = 1; @@ -856,8 +876,13 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int tmp->overflow = constraint->range.overflow; #ifdef SYM_RANGE } else if (narrowing && ssa->var_info[constraint->max_ssa_var].has_range) { - tmp->max = ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max; - tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow; + if (add_will_overflow(ssa->var_info[constraint->max_ssa_var].range.max, constraint->range.max)) { + tmp->overflow = 1; + tmp->max = ZEND_LONG_MAX; + } else { + tmp->max = ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max; + tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow; + } #endif } else { tmp->max = ZEND_LONG_MAX; |