}
/* }}} */
-ZEND_API zend_bool zend_binary_op_produces_numeric_string_error(uint32_t opcode, zval *op1, zval *op2) /* {{{ */
+ZEND_API zend_bool zend_binary_op_produces_error(uint32_t opcode, zval *op1, zval *op2) /* {{{ */
{
+ if ((opcode == ZEND_CONCAT || opcode == ZEND_FAST_CONCAT)) {
+ /* Array to string warning. */
+ return Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY;
+ }
+
if (!(opcode == ZEND_ADD || opcode == ZEND_SUB || opcode == ZEND_MUL || opcode == ZEND_DIV
- || opcode == ZEND_POW || opcode == ZEND_MOD || opcode == ZEND_SL || opcode == ZEND_SR
- || opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)) {
+ || opcode == ZEND_POW || opcode == ZEND_MOD || opcode == ZEND_SL || opcode == ZEND_SR
+ || opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)) {
+ /* Only the numeric operations throw errors. */
return 0;
}
+ if (Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY) {
+ if (opcode == ZEND_ADD && Z_TYPE_P(op1) == IS_ARRAY && Z_TYPE_P(op2) == IS_ARRAY) {
+ /* Adding two arrays is allowed. */
+ return 0;
+ }
+ if (opcode == ZEND_ADD || opcode == ZEND_SUB || opcode == ZEND_MUL || opcode == ZEND_POW
+ || opcode == ZEND_DIV) {
+ /* These operators throw when one of the operands is an array. */
+ return 1;
+ }
+ }
+
/* While basic arithmetic operators always produce numeric string errors,
* bitwise operators don't produce errors if both operands are strings */
if ((opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)
return 1;
}
- return 0;
-}
-/* }}} */
-
-ZEND_API zend_bool zend_binary_op_produces_array_conversion_error(uint32_t opcode, zval *op1, zval *op2) /* {{{ */
-{
- if (opcode == ZEND_CONCAT && (Z_TYPE_P(op1) == IS_ARRAY || Z_TYPE_P(op2) == IS_ARRAY)) {
+ if ((opcode == ZEND_DIV || opcode == ZEND_MOD) && zval_get_long(op2) == 0) {
+ /* Division by zero throws an error. */
+ return 1;
+ }
+ if ((opcode == ZEND_SL || opcode == ZEND_SR) && zval_get_long(op2) < 0) {
+ /* Shift by negative number throws an error. */
return 1;
}
static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
{
- binary_op_type fn = get_binary_op(opcode);
-
- /* don't evaluate division by zero at compile-time */
- if ((opcode == ZEND_DIV || opcode == ZEND_MOD) &&
- zval_get_long(op2) == 0) {
- return 0;
- } else if ((opcode == ZEND_SL || opcode == ZEND_SR) &&
- zval_get_long(op2) < 0) {
- return 0;
- }
-
- /* don't evaluate numeric string error-producing operations at compile-time */
- if (zend_binary_op_produces_numeric_string_error(opcode, op1, op2)) {
- return 0;
- }
- /* don't evaluate array to string conversions at compile-time */
- if (zend_binary_op_produces_array_conversion_error(opcode, op1, op2)) {
+ if (zend_binary_op_produces_error(opcode, op1, op2)) {
return 0;
}
+ binary_op_type fn = get_binary_op(opcode);
fn(result, op1, op2);
return 1;
}
binary_op_type binary_op = get_binary_op(opcode);
int er, ret;
- if (zend_binary_op_produces_numeric_string_error(opcode, op1, op2)) {
- /* produces numeric string E_NOTICE/E_WARNING */
+ if (zend_binary_op_produces_error(opcode, op1, op2)) {
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);