diff options
-rw-r--r-- | ext/gmp/gmp.c | 10 | ||||
-rw-r--r-- | ext/gmp/tests/bug70284.phpt | 50 |
2 files changed, 55 insertions, 5 deletions
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 575dab8a5b..c7cdef736f 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -630,7 +630,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c { mpz_ptr gmpnum; const unsigned char *p, *max; - zval zv, *zv_ptr = &zv; + zval *zv_ptr; int retval = FAILURE; php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; @@ -640,7 +640,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c p = buf; max = buf + buf_len; - INIT_ZVAL(zv); + ALLOC_INIT_ZVAL(zv_ptr); if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC) || Z_TYPE_P(zv_ptr) != IS_STRING || convert_to_gmp(gmpnum, zv_ptr, 10 TSRMLS_CC) == FAILURE @@ -648,9 +648,9 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c zend_throw_exception(NULL, "Could not unserialize number", 0 TSRMLS_CC); goto exit; } - zval_dtor(&zv); + var_push_dtor_no_addref(&unserialize_data, &zv_ptr); - INIT_ZVAL(zv); + ALLOC_INIT_ZVAL(zv_ptr); if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC) || Z_TYPE_P(zv_ptr) != IS_ARRAY ) { @@ -667,7 +667,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c retval = SUCCESS; exit: - zval_dtor(&zv); + var_push_dtor_no_addref(&unserialize_data, &zv_ptr); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return retval; } diff --git a/ext/gmp/tests/bug70284.phpt b/ext/gmp/tests/bug70284.phpt new file mode 100644 index 0000000000..ab17c0fc1c --- /dev/null +++ b/ext/gmp/tests/bug70284.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug #70284 (Use after free vulnerability in unserialize() with GMP) +--SKIPIF-- +<?php if (!extension_loaded("gmp")) print "skip"; ?> +--FILE-- +<?php + +$inner = 'r:2;a:1:{i:0;a:1:{i:0;r:4;}}'; +$exploit = 'a:2:{i:0;s:1:"1";i:1;C:3:"GMP":'.strlen($inner).':{'.$inner.'}}'; + +$data = unserialize($exploit); + +$fakezval = ptr2str(1122334455); +$fakezval .= ptr2str(0); +$fakezval .= "\x00\x00\x00\x00"; +$fakezval .= "\x01"; +$fakezval .= "\x00"; +$fakezval .= "\x00\x00"; + +for ($i = 0; $i < 5; $i++) { + $v[$i] = $fakezval.$i; +} + +var_dump($data); + +function ptr2str($ptr) +{ +$out = ''; + for ($i = 0; $i < 8; $i++) { + $out .= chr($ptr & 0xff); + $ptr >>= 8; + } + return $out; +} +?> +--EXPECTF-- +array(2) { + [0]=> + string(1) "1" + [1]=> + object(GMP)#%d (2) { + [0]=> + array(1) { + [0]=> + NULL + } + ["num"]=> + string(1) "1" + } +} |