components/php/php56/patches/70284.patch
changeset 6715 70440209f302
parent 6714 af94afe100ff
child 6716 6e7ab6702602
equal deleted inserted replaced
6714:af94afe100ff 6715:70440209f302
     1 # Source: upstream
       
     2 # https://github.com/php/php-src/commit/d735957cb5f8fee8d13ae68cf75300306c84374f.patch
       
     3 # https://bugs.php.net/bug.php?id=70284
       
     4 # Security
       
     5 
       
     6 From d735957cb5f8fee8d13ae68cf75300306c84374f Mon Sep 17 00:00:00 2001
       
     7 From: Stanislav Malyshev <[email protected]>
       
     8 Date: Sun, 23 Aug 2015 13:46:19 -0700
       
     9 Subject: [PATCH] Fix bug ##70284 (Use after free vulnerability in
       
    10  unserialize() with GMP)
       
    11 
       
    12 ---
       
    13  ext/gmp/gmp.c               | 10 ++++-----
       
    14  ext/gmp/tests/bug70284.phpt | 50 +++++++++++++++++++++++++++++++++++++++++++++
       
    15  2 files changed, 55 insertions(+), 5 deletions(-)
       
    16  create mode 100644 ext/gmp/tests/bug70284.phpt
       
    17 
       
    18 diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
       
    19 index 575dab8..c7cdef7 100644
       
    20 --- a/ext/gmp/gmp.c
       
    21 +++ b/ext/gmp/gmp.c
       
    22 @@ -630,7 +630,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c
       
    23  {
       
    24  	mpz_ptr gmpnum;
       
    25  	const unsigned char *p, *max;
       
    26 -	zval zv, *zv_ptr = &zv;
       
    27 +	zval *zv_ptr;
       
    28  	int retval = FAILURE;
       
    29  	php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data;
       
    30  
       
    31 @@ -640,7 +640,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c
       
    32  	p = buf;
       
    33  	max = buf + buf_len;
       
    34  
       
    35 -	INIT_ZVAL(zv);
       
    36 +	ALLOC_INIT_ZVAL(zv_ptr);
       
    37  	if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC)
       
    38  		|| Z_TYPE_P(zv_ptr) != IS_STRING
       
    39  		|| convert_to_gmp(gmpnum, zv_ptr, 10 TSRMLS_CC) == FAILURE
       
    40 @@ -648,9 +648,9 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c
       
    41  		zend_throw_exception(NULL, "Could not unserialize number", 0 TSRMLS_CC);
       
    42  		goto exit;
       
    43  	}
       
    44 -	zval_dtor(&zv);
       
    45 +	var_push_dtor_no_addref(&unserialize_data, &zv_ptr);
       
    46  
       
    47 -	INIT_ZVAL(zv);
       
    48 +	ALLOC_INIT_ZVAL(zv_ptr);
       
    49  	if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC)
       
    50  		|| Z_TYPE_P(zv_ptr) != IS_ARRAY
       
    51  	) {
       
    52 @@ -667,7 +667,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c
       
    53  
       
    54  	retval = SUCCESS;
       
    55  exit:
       
    56 -	zval_dtor(&zv);
       
    57 +	var_push_dtor_no_addref(&unserialize_data, &zv_ptr);
       
    58  	PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data);
       
    59  	return retval;
       
    60  }
       
    61 diff --git a/ext/gmp/tests/bug70284.phpt b/ext/gmp/tests/bug70284.phpt
       
    62 new file mode 100644
       
    63 index 0000000..ab17c0f
       
    64 --- /dev/null
       
    65 +++ b/ext/gmp/tests/bug70284.phpt
       
    66 @@ -0,0 +1,50 @@
       
    67 +--TEST--
       
    68 +Bug #70284 (Use after free vulnerability in unserialize() with GMP)
       
    69 +--SKIPIF--
       
    70 +<?php if (!extension_loaded("gmp")) print "skip"; ?>
       
    71 +--FILE--
       
    72 +<?php
       
    73 +
       
    74 +$inner = 'r:2;a:1:{i:0;a:1:{i:0;r:4;}}';
       
    75 +$exploit = 'a:2:{i:0;s:1:"1";i:1;C:3:"GMP":'.strlen($inner).':{'.$inner.'}}';
       
    76 +
       
    77 +$data = unserialize($exploit);
       
    78 +
       
    79 +$fakezval = ptr2str(1122334455);
       
    80 +$fakezval .= ptr2str(0);
       
    81 +$fakezval .= "\x00\x00\x00\x00";
       
    82 +$fakezval .= "\x01";
       
    83 +$fakezval .= "\x00";
       
    84 +$fakezval .= "\x00\x00";
       
    85 +
       
    86 +for ($i = 0; $i < 5; $i++) {
       
    87 +	$v[$i] = $fakezval.$i;
       
    88 +}
       
    89 +
       
    90 +var_dump($data);
       
    91 +
       
    92 +function ptr2str($ptr)
       
    93 +{
       
    94 +$out = '';
       
    95 +	for ($i = 0; $i < 8; $i++) {
       
    96 +		$out .= chr($ptr & 0xff);
       
    97 +		$ptr >>= 8;
       
    98 +	}
       
    99 +	return $out;
       
   100 +}
       
   101 +?>
       
   102 +--EXPECTF--
       
   103 +array(2) {
       
   104 +  [0]=>
       
   105 +  string(1) "1"
       
   106 +  [1]=>
       
   107 +  object(GMP)#%d (2) {
       
   108 +    [0]=>
       
   109 +    array(1) {
       
   110 +      [0]=>
       
   111 +      NULL
       
   112 +    }
       
   113 +    ["num"]=>
       
   114 +    string(1) "1"
       
   115 +  }
       
   116 +}
       
   117