Skip to content

Commit 3a97b8b

Browse files
committed
Backport "Avoid UB in overflow checks"
Cherry-pick of bb940d9 without the JIT parts.
1 parent ccfe6c8 commit 3a97b8b

File tree

3 files changed

+23
-20
lines changed

3 files changed

+23
-20
lines changed

ext/opcache/Optimizer/zend_inference.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -575,19 +575,21 @@ static int zend_inference_calc_binary_op_range(
575575
op2_min = OP2_MIN_RANGE();
576576
op1_max = OP1_MAX_RANGE();
577577
op2_max = OP2_MAX_RANGE();
578-
tmp->min = op1_min + op2_min;
579-
tmp->max = op1_max + op2_max;
580578
if (OP1_RANGE_UNDERFLOW() ||
581579
OP2_RANGE_UNDERFLOW() ||
582-
(op1_min < 0 && op2_min < 0 && tmp->min >= 0)) {
580+
zend_add_will_overflow(op1_min, op2_min)) {
583581
tmp->underflow = 1;
584582
tmp->min = ZEND_LONG_MIN;
583+
} else {
584+
tmp->min = op1_min + op2_min;
585585
}
586586
if (OP1_RANGE_OVERFLOW() ||
587587
OP2_RANGE_OVERFLOW() ||
588-
(op1_max > 0 && op2_max > 0 && tmp->max <= 0)) {
588+
zend_add_will_overflow(op1_max, op2_max)) {
589589
tmp->overflow = 1;
590590
tmp->max = ZEND_LONG_MAX;
591+
} else {
592+
tmp->max = op1_max + op2_max;
591593
}
592594
return 1;
593595
}
@@ -598,19 +600,21 @@ static int zend_inference_calc_binary_op_range(
598600
op2_min = OP2_MIN_RANGE();
599601
op1_max = OP1_MAX_RANGE();
600602
op2_max = OP2_MAX_RANGE();
601-
tmp->min = op1_min - op2_max;
602-
tmp->max = op1_max - op2_min;
603603
if (OP1_RANGE_UNDERFLOW() ||
604604
OP2_RANGE_OVERFLOW() ||
605-
(op1_min < 0 && op2_max > 0 && tmp->min >= 0)) {
605+
zend_sub_will_overflow(op1_min, op2_max)) {
606606
tmp->underflow = 1;
607607
tmp->min = ZEND_LONG_MIN;
608+
} else {
609+
tmp->min = op1_min - op2_max;
608610
}
609611
if (OP1_RANGE_OVERFLOW() ||
610612
OP2_RANGE_UNDERFLOW() ||
611-
(op1_max > 0 && op2_min < 0 && tmp->max <= 0)) {
613+
zend_sub_will_overflow(op1_max, op2_min)) {
612614
tmp->overflow = 1;
613615
tmp->max = ZEND_LONG_MAX;
616+
} else {
617+
tmp->max = op1_max - op2_min;
614618
}
615619
return 1;
616620
}

ext/opcache/Optimizer/zend_inference.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,14 @@ DEFINE_SSA_OP_DEF_INFO(result)
238238
#define OP2_DATA_DEF_INFO() (_ssa_op2_def_info(op_array, ssa, (opline+1)))
239239
#define RES_INFO() (_ssa_result_def_info(op_array, ssa, opline))
240240

241+
static zend_always_inline zend_bool zend_add_will_overflow(zend_long a, zend_long b) {
242+
return (b > 0 && a > ZEND_LONG_MAX - b)
243+
|| (b < 0 && a < ZEND_LONG_MIN - b);
244+
}
245+
static zend_always_inline zend_bool zend_sub_will_overflow(zend_long a, zend_long b) {
246+
return (b > 0 && a < ZEND_LONG_MIN + b)
247+
|| (b < 0 && a > ZEND_LONG_MAX + b);
248+
}
241249

242250
BEGIN_EXTERN_C()
243251

ext/opcache/Optimizer/zend_ssa.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,6 @@ static int find_adjusted_tmp_var(const zend_op_array *op_array, uint32_t build_f
221221
}
222222
/* }}} */
223223

224-
static inline zend_bool add_will_overflow(zend_long a, zend_long b) {
225-
return (b > 0 && a > ZEND_LONG_MAX - b)
226-
|| (b < 0 && a < ZEND_LONG_MIN - b);
227-
}
228-
static inline zend_bool sub_will_overflow(zend_long a, zend_long b) {
229-
return (b > 0 && a < ZEND_LONG_MIN + b)
230-
|| (b < 0 && a > ZEND_LONG_MAX + b);
231-
}
232-
233224
/* e-SSA construction: Pi placement (Pi is actually a Phi with single
234225
* source and constraint).
235226
* Order of Phis is importent, Pis must be placed before Phis
@@ -291,7 +282,7 @@ static void place_essa_pis(
291282
}
292283

293284
if (var1 >= 0 && var2 >= 0) {
294-
if (!sub_will_overflow(val1, val2) && !sub_will_overflow(val2, val1)) {
285+
if (!zend_sub_will_overflow(val1, val2) && !zend_sub_will_overflow(val2, val1)) {
295286
zend_long tmp = val1;
296287
val1 -= val2;
297288
val2 -= tmp;
@@ -316,7 +307,7 @@ static void place_essa_pis(
316307
} else {
317308
var1 = -1;
318309
}
319-
if (!add_will_overflow(val2, add_val2)) {
310+
if (!zend_add_will_overflow(val2, add_val2)) {
320311
val2 += add_val2;
321312
} else {
322313
var1 = -1;
@@ -337,7 +328,7 @@ static void place_essa_pis(
337328
} else {
338329
var2 = -1;
339330
}
340-
if (!add_will_overflow(val1, add_val1)) {
331+
if (!zend_add_will_overflow(val1, add_val1)) {
341332
val1 += add_val1;
342333
} else {
343334
var2 = -1;

0 commit comments

Comments
 (0)