]> granicus.if.org Git - php/commitdiff
More accurate symbolic constraints oferflow/unserflow handling (better fix for bug...
authorDmitry Stogov <dmitry@zend.com>
Tue, 13 Mar 2018 07:44:53 +0000 (10:44 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 13 Mar 2018 07:44:53 +0000 (10:44 +0300)
ext/opcache/Optimizer/zend_inference.c

index 9f930a1ab68f14e98080d5b79ac72f38a9147f2d..84ca1e92454c31984a21d2d892a7f0d6f3d4e1e2 100644 (file)
        } 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 {