]> granicus.if.org Git - php/commitdiff
Fix bug #67917 (gmp compound assignment operator leak)
authorNikita Popov <nikic@php.net>
Wed, 27 Aug 2014 20:15:20 +0000 (22:15 +0200)
committerNikita Popov <nikic@php.net>
Wed, 27 Aug 2014 20:16:20 +0000 (22:16 +0200)
NEWS
ext/gmp/bug67917.phpt [new file with mode: 0644]
ext/gmp/gmp.c

diff --git a/NEWS b/NEWS
index 18f83de048720f4293c1f54991ebeb7c6777c44b..d859332f012ba2f7996da3061104df45e511b697 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,14 +6,18 @@ PHP                                                                        NEWS
 - Core:
   . Fixed bug #67878 (program_prefix not honoured in man pages). (Remi)
 
-- GD
+- GD:
   . Made fontFetch's path parser thread-safe. (Sara)
 
+- GMP:
+  . Fixed bug #67917 (Using GMP objects with overloaded operators can cause
+    memory exhaustion). (Nikita Popov)
+
 - MySQLi:
   . Fixed bug #67839 (mysqli does not handle 4-byte floats correctly). (Keyur)
 
-- OpenSSL
-  . Fixed bug #67850 (extension won't build if openssl compiled without SSLv3)
+- OpenSSL:
+  . Fixed bug #67850 (extension won't build if openssl compiled without SSLv3).
     (Daniel Lowrey)
 
 28 Aug 2014, PHP 5.6.0
diff --git a/ext/gmp/bug67917.phpt b/ext/gmp/bug67917.phpt
new file mode 100644 (file)
index 0000000..93d46cb
--- /dev/null
@@ -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)
index cd50896cc7d4c17997c7a513416f632bd7fb704f..486088bbafd6fc06b4f6771a63ef469d2b6794d0 100644 (file)
@@ -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);