From e8109e09aaca9617806f41ae4d5b92460e077769 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 7 Dec 2016 00:41:07 +0300 Subject: Fixed memory leaks caused by exceptions thrown from destructors. --- Zend/zend_operators.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) (limited to 'Zend/zend_operators.c') diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 2d6df66a68..9f62db9aaa 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -217,6 +217,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ ZVAL_COPY(&(holder), op); \ convert_to_long_base(&(holder), 10); \ if (UNEXPECTED(EG(exception))) { \ + if (result != op1) { \ + ZVAL_UNDEF(result); \ + } \ return FAILURE; \ } \ if (Z_TYPE(holder) == IS_LONG) { \ @@ -252,7 +255,7 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ /* }}} */ -#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, op, op_func) \ +#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, op, op_func) \ do { \ if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { \ if (Z_ISREF_P(op1)) { \ @@ -265,6 +268,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(op, op_func); \ op1_lval = _zval_get_long_func_noisy(op1); \ if (UNEXPECTED(EG(exception))) { \ + if (result != op1) { \ + ZVAL_UNDEF(result); \ + } \ return FAILURE; \ } \ } else { \ @@ -283,6 +289,9 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(op); \ op2_lval = _zval_get_long_func_noisy(op2); \ if (UNEXPECTED(EG(exception))) { \ + if (result != op1) { \ + ZVAL_UNDEF(result); \ + } \ return FAILURE; \ } \ } else { \ @@ -936,6 +945,9 @@ ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* { zendi_convert_scalar_to_number(op2, op2_copy, result, 0); converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; /* unknown datatype */ } @@ -978,6 +990,9 @@ ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* { zendi_convert_scalar_to_number(op2, op2_copy, result, 0); converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; /* unknown datatype */ } @@ -1025,6 +1040,9 @@ ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* { zendi_convert_scalar_to_number(op2, op2_copy, result, 0); converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; /* unknown datatype */ } @@ -1113,6 +1131,9 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* { } converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; } @@ -1178,6 +1199,9 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* { zendi_convert_scalar_to_number(op2, op2_copy, result, 0); converted = 1; } else { + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; /* unknown datatype */ } @@ -1190,7 +1214,7 @@ ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* { { zend_long op1_lval, op2_lval; - convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_MOD, mod_function); + convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_MOD, mod_function); if (op2_lval == 0) { /* modulus by zero */ @@ -1330,6 +1354,9 @@ try_again: default: ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT); + if (result != op1) { + ZVAL_UNDEF(result); + } zend_throw_error(NULL, "Unsupported operand types"); return FAILURE; } @@ -1389,6 +1416,9 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function); op1_lval = _zval_get_long_func_noisy(op1); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1398,6 +1428,9 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR); op2_lval = _zval_get_long_func_noisy(op2); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1465,6 +1498,9 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function); op1_lval = _zval_get_long_func_noisy(op1); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1474,6 +1510,9 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND); op2_lval = _zval_get_long_func_noisy(op2); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1541,6 +1580,9 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function); op1_lval = _zval_get_long_func_noisy(op1); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1550,6 +1592,9 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR); op2_lval = _zval_get_long_func_noisy(op2); if (UNEXPECTED(EG(exception))) { + if (result != op1) { + ZVAL_UNDEF(result); + } return FAILURE; } } else { @@ -1568,7 +1613,7 @@ ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op { zend_long op1_lval, op2_lval; - convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SL, shift_left_function); + convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_SL, shift_left_function); /* prevent wrapping quirkiness on some processors where << 64 + x == << x */ if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) { @@ -1604,7 +1649,7 @@ ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *o { zend_long op1_lval, op2_lval; - convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SR, shift_right_function); + convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, ZEND_SR, shift_right_function); /* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */ if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) { @@ -1653,6 +1698,9 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) / if (use_copy1) { if (UNEXPECTED(EG(exception))) { zval_dtor(&op1_copy); + if (orig_op1 != result) { + ZVAL_UNDEF(result); + } return FAILURE; } if (result == op1) { @@ -1678,6 +1726,9 @@ ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) / zval_dtor(op1); } zval_dtor(&op2_copy); + if (orig_op1 != result) { + ZVAL_UNDEF(result); + } return FAILURE; } op2 = &op2_copy; -- cgit v1.2.1