diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/gmp/bug67917.phpt | 17 | ||||
| -rw-r--r-- | ext/gmp/gmp.c | 22 |
2 files changed, 38 insertions, 1 deletions
diff --git a/ext/gmp/bug67917.phpt b/ext/gmp/bug67917.phpt new file mode 100644 index 0000000000..93d46cbb66 --- /dev/null +++ b/ext/gmp/bug67917.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #67917: Using GMP objects with overloaded operators can cause memory exhaustion +--FILE-- +<?php + +$mem1 = memory_get_usage(); +for ($i = 0; $i < 1000; $i++) { + $gmp = gmp_init(42); + $gmp <<= 1; +} +$mem2 = memory_get_usage(); + +var_dump($mem2 - $mem1 < 100000); + +?> +--EXPECT-- +bool(true) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index cd50896cc7..486088bbaf 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -523,7 +523,7 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva gmp_zval_unary_op(result, op1, op TSRMLS_CC); \ return SUCCESS; -static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ +static int gmp_do_operation_ex(zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ { switch (opcode) { case ZEND_ADD: @@ -560,6 +560,26 @@ static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op } /* }}} */ +static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ +{ + zval op1_copy; + int retval; + + if (result == op1) { + ZVAL_COPY_VALUE(&op1_copy, op1); + op1 = &op1_copy; + } + + retval = gmp_do_operation_ex(opcode, result, op1, op2 TSRMLS_CC); + + if (retval == SUCCESS && op1 == &op1_copy) { + zval_dtor(op1); + } + + return retval; +} +/* }}} */ + static int gmp_compare(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ { gmp_cmp(result, op1, op2 TSRMLS_CC); |
