]> granicus.if.org Git - php/commitdiff
Fix Pi constraint for -LONG_MIN adjustments
authorNikita Popov <nikic@php.net>
Sat, 19 Dec 2015 22:47:08 +0000 (23:47 +0100)
committerNikita Popov <nikic@php.net>
Sat, 19 Dec 2015 23:06:12 +0000 (00:06 +0100)
-LONG_MIN == LONG_MIN so bad things will happen.
Example of JIT miscompile:

    function test($n) {
if ($n + PHP_INT_MIN == 0) {
    $n2 = (int) ($n + PHP_INT_MAX);
    var_dump($n2);
}
    }
    test(PHP_INT_MAX + 1);

ext/opcache/Optimizer/zend_ssa.c

index f18edfa4270e2b03a385b9731f2ce53eaea427cb..5dd55b8ddae67a03de8a91a8f8a4fbced8c6e42a 100644 (file)
@@ -96,12 +96,14 @@ static int find_adjusted_tmp_var(const zend_op_array *op_array, uint32_t build_f
                } else if (op->opcode == ZEND_ADD) {
                        if (op->op1_type == IS_CV &&
                                op->op2_type == IS_CONST &&
-                               Z_TYPE_P(CRT_CONSTANT(op->op2)) == IS_LONG) {
+                               Z_TYPE_P(CRT_CONSTANT(op->op2)) == IS_LONG &&
+                               Z_LVAL_P(CRT_CONSTANT(op->op2)) != LONG_MIN) {
                                *adjustment = -Z_LVAL_P(CRT_CONSTANT(op->op2));
                                return EX_VAR_TO_NUM(op->op1.var);
                        } else if (op->op2_type == IS_CV &&
                                           op->op1_type == IS_CONST &&
-                                          Z_TYPE_P(CRT_CONSTANT(op->op1)) == IS_LONG) {
+                                          Z_TYPE_P(CRT_CONSTANT(op->op1)) == IS_LONG &&
+                                          Z_LVAL_P(CRT_CONSTANT(op->op1)) != LONG_MIN) {
                                *adjustment = -Z_LVAL_P(CRT_CONSTANT(op->op1));
                                return EX_VAR_TO_NUM(op->op2.var);
                        }