]> granicus.if.org Git - php/commitdiff
Check for exceptional cases before actual constant evaluation.
authorDmitry Stogov <dmitry@zend.com>
Tue, 4 Jul 2017 13:09:28 +0000 (16:09 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 4 Jul 2017 13:09:28 +0000 (16:09 +0300)
ext/opcache/Optimizer/zend_optimizer.c

index bf7eb4ba621e0f9752bb5c6dda5be14c60759928..2179cf267c00f7ca2d057cdfa45724c1e1f9d8c5 100644 (file)
@@ -58,19 +58,47 @@ int zend_optimizer_eval_binary_op(zval *result, zend_uchar opcode, zval *op1, zv
        binary_op_type binary_op = get_binary_op(opcode);
        int er, ret;
 
-       if ((opcode == ZEND_DIV || opcode == ZEND_MOD) &&
-               zval_get_long(op2) == 0) {
-               /* div by 0 */
-               return FAILURE;
-       } else if ((opcode == ZEND_SL || opcode == ZEND_SR) &&
-               zval_get_long(op2) < 0) {
-               /* shift by negative number */
-               return FAILURE;
-       } else if (zend_binary_op_produces_numeric_string_error(opcode, op1, op2)) {
+       if (zend_binary_op_produces_numeric_string_error(opcode, op1, op2)) {
                /* produces numeric string E_NOTICE/E_WARNING */
                return FAILURE;
        }
 
+       switch (opcode) {
+               case ZEND_ADD:
+                       if ((Z_TYPE_P(op1) == IS_ARRAY
+                         || Z_TYPE_P(op2) == IS_ARRAY)
+                        && Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
+                               /* produces "Unsupported operand types" exception */
+                               return FAILURE;
+                       }
+                       break;
+               case ZEND_DIV:
+               case ZEND_MOD:
+                       if (zval_get_long(op2) == 0) {
+                               /* division by 0 */
+                               return FAILURE;
+                       }
+                       /* break missing intentionally */
+               case ZEND_SUB:
+               case ZEND_MUL:
+               case ZEND_POW:
+               case ZEND_CONCAT:
+               case ZEND_FAST_CONCAT:
+                       if (Z_TYPE_P(op1) == IS_ARRAY
+                        || Z_TYPE_P(op2) == IS_ARRAY) {
+                               /* produces "Unsupported operand types" exception */
+                               return FAILURE;
+                       }
+                       break;
+               case ZEND_SL:
+               case ZEND_SR:
+                       if (zval_get_long(op2) < 0) {
+                               /* shift by negative number */
+                               return FAILURE;
+                       }
+                       break;
+       }
+
        er = EG(error_reporting);
        EG(error_reporting) = 0;
        ret = binary_op(result, op1, op2);
@@ -85,6 +113,13 @@ int zend_optimizer_eval_unary_op(zval *result, zend_uchar opcode, zval *op1) /*
        unary_op_type unary_op = get_unary_op(opcode);
 
        if (unary_op) {
+               if (opcode == ZEND_BW_NOT
+                && Z_TYPE_P(op1) != IS_LONG
+                && Z_TYPE_P(op1) != IS_DOUBLE
+                && Z_TYPE_P(op1) != IS_STRING) {
+                       /* produces "Unsupported operand types" exception */
+                       return FAILURE;
+               }
                return unary_op(result, op1);
        } else { /* ZEND_BOOL */
                ZVAL_BOOL(result, zend_is_true(op1));