From 44ba557de5c0d767ff6ccfcc2c8bde7d7c0746fe Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 13 Mar 2018 10:44:53 +0300 Subject: More accurate symbolic constraints oferflow/unserflow handling (better fix for bug #76074). --- ext/opcache/Optimizer/zend_inference.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'ext/opcache') diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 9f930a1ab6..84ca1e9245 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -158,15 +158,12 @@ } 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); + return (b > 0 && a > ZEND_LONG_MAX - 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); + +static inline zend_bool add_will_underflow(zend_long a, zend_long b) { + return (b < 0 && a < ZEND_LONG_MIN - 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) /* {{{ */ { @@ -836,8 +833,13 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int tmp->min = MAX(constraint->range.min, tmp->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->underflow; - if (!add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) { + if ((ssa->var_info[constraint->min_ssa_var].range.underflow + || add_will_underflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) + && tmp->underflow) { + tmp->underflow = 1; + tmp->min = ZEND_LONG_MIN; + } else { + tmp->underflow = 0; tmp->min = MAX(ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min, tmp->min); } #endif @@ -847,10 +849,15 @@ 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) { - if (!add_will_overflow(ssa->var_info[constraint->max_ssa_var].range.max, constraint->range.max)) { + if ((ssa->var_info[constraint->min_ssa_var].range.overflow + || add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.max, constraint->range.max)) + && tmp->overflow) { + tmp->overflow = 1; + tmp->max = ZEND_LONG_MAX; + } else { + tmp->overflow = 0; 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 } } else if (narrowing) { @@ -859,7 +866,7 @@ 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) { - if (add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) { + if (add_will_underflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) { tmp->underflow = 1; tmp->min = ZEND_LONG_MIN; } else { -- cgit v1.2.1