diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 9820bb6d6b0..a971386bf59 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -39,7 +39,8 @@ #define SYM_RANGE /* Whether to handle negative range constraints */ -#define NEG_RANGE +/* Negative range inference is buggy, so disabled for now */ +#undef NEG_RANGE /* Number of warmup passes to use prior to widening */ #define RANGE_WARMUP_PASSES 16 @@ -2054,6 +2055,14 @@ static uint32_t binary_op_result_type( uint32_t tmp = 0; uint32_t t1_type = (t1 & MAY_BE_ANY) | (t1 & MAY_BE_UNDEF ? MAY_BE_NULL : 0); uint32_t t2_type = (t2 & MAY_BE_ANY) | (t2 & MAY_BE_UNDEF ? MAY_BE_NULL : 0); + + /* Handle potentially overloaded operators. + * This could be made more precise by checking the class type, if known. */ + if ((t1_type & MAY_BE_OBJECT) || (t2_type & MAY_BE_OBJECT)) { + /* This is somewhat GMP specific. */ + tmp |= MAY_BE_OBJECT | MAY_BE_FALSE | MAY_BE_RC1; + } + switch (opcode) { case ZEND_ADD: if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) { @@ -2108,7 +2117,7 @@ static uint32_t binary_op_result_type( * handling */ break; case ZEND_MOD: - tmp = MAY_BE_LONG; + tmp |= MAY_BE_LONG; /* Division by zero results in an exception, so it doesn't need any special handling */ break; case ZEND_BW_OR: @@ -2123,7 +2132,7 @@ static uint32_t binary_op_result_type( break; case ZEND_SL: case ZEND_SR: - tmp = MAY_BE_LONG; + tmp |= MAY_BE_LONG; break; case ZEND_CONCAT: case ZEND_FAST_CONCAT: @@ -2251,6 +2260,10 @@ static int zend_update_type_info(const zend_op_array *op_array, if (t1 & (MAY_BE_ANY-MAY_BE_STRING)) { tmp |= MAY_BE_LONG; } + if (t1 & MAY_BE_OBJECT) { + /* Potentially overloaded operator. */ + tmp |= MAY_BE_OBJECT | MAY_BE_RC1; + } UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); break; case ZEND_BEGIN_SILENCE: diff --git a/ext/opcache/tests/neg_range_inference.phpt b/ext/opcache/tests/neg_range_inference.phpt new file mode 100644 index 00000000000..b3dd4a72bed --- /dev/null +++ b/ext/opcache/tests/neg_range_inference.phpt @@ -0,0 +1,26 @@ +--TEST-- +Incorrect negative range inference +--FILE-- + +--EXPECT-- +int(1) +int(1) +int(1) +int(1) +int(1) +int(0) +int(0) +int(0) +int(0)