Bug #71221 [Csd]: Null pointer deref (segfault) in get_defined_vars via ob_start
[email protected] ("hugh at allthethings dot co dot nz")
| Newsgroups | php.bugs |
|---|---|
| Message-ID | <[email protected]> |
Edit report at https://bugs.php.net/bug.php?id=71221&edit=1
ID: 71221
User updated by: hugh at allthethings dot co dot nz
Reported by: hugh at allthethings dot co dot nz
Summary: Null pointer deref (segfault) in get_defined_vars
via ob_start
Status: Closed
Type: Bug
Package: Reproducible crash
Operating System: Linux
PHP Version: 7.0.1
Block user comment: N
Private report: N
New Comment:
Thanks for the quick fix! Will there be a cve issued for this?
Previous Comments:
------------------------------------------------------------------------
[2015-12-26 04:33:09] [email protected]
Automatic comment on behalf of [email protected]
Revision: http://git.php.net/?p=php-src.git;a=commit;h=6700be67f58611d08bbacc44f327ce98ed0473c9
Log: Fixed bug #71221 (Null pointer deref (segfault) in get_defined_vars via ob_start)
------------------------------------------------------------------------
[2015-12-25 20:14:28] hugh at allthethings dot co dot nz
Description:
------------
Description:
------------
Found this using afl-fuzz, see http://lcamtuf.coredump.cx/afl/
Affects 7.0.0, 7.0.1, 7.0.2, but none of the 5.6 series or before.
To reproduce, compile PHP normally, then run ./sapi/cli/php with the test script
<?php ob_start( get_defined_vars ); ?>
You should get a segfault.
The test case is similar to bug #71220, and the cause is also similar, but in a different location.
What is happening is the call to get_defined_vars actually goes to the function zif_get_defined_vars in Zend/zend_builtin_functions.c, where the symbol table created on line 1948 with zend_rebuild_symbol_table() returns null, and is then passed into zend_array_dup on line 1950, which produces the stack trace below.
A patch to fix would be:
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 6faa57c..754bca9 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -1947,6 +1947,10 @@ ZEND_FUNCTION(get_defined_vars)
{
zend_array *symbol_table = zend_rebuild_symbol_table();
+ if (symbol_table == NULL) {
+ return;
+ }
+
RETURN_ARR(zend_array_dup(symbol_table));
}
/* }}} */
Test script:
---------------
<?php ob_start( get_defined_vars ); ?>
Expected result:
----------------
No crash
Actual result:
--------------
When compiled to ASAN, the following backtrace happens:
$ ./php-7.0.2-asan ~/php-crash-7.0-get_defined_vars
ASAN:SIGSEGV
=================================================================
==22087== ERROR: AddressSanitizer: SEGV on unknown address 0x000000000020 (pc 0x00000137b99c sp 0x7ffedd5eae10 bp 0x7f7d43e57218 T0)
AddressSanitizer can not provide additional info.
#0 0x137b99b in zend_array_dup /root/php-src/Zend/zend_hash.c:1780
#1 0x13adf6f in zif_get_defined_vars /root/php-src/Zend/zend_builtin_functions.c:1950
#2 0x11e8793 in zend_call_function /root/php-src/Zend/zend_execute_API.c:881
#3 0x12f28ba in zend_fcall_info_call /root/php-src/Zend/zend_API.c:3574
#4 0xf5f746 in php_output_handler_op /root/php-src/main/output.c:960
#5 0xf5f746 in php_output_stack_pop /root/php-src/main/output.c:1221
#6 0xf5f746 in php_output_end_all /root/php-src/main/output.c:341
#7 0xeb5014 in php_request_shutdown /root/php-src/main/main.c:1777
#8 0x19bd1a2 in do_cli /root/php-src/sapi/cli/php_cli.c:1142
#9 0x472e0a in main /root/php-src/sapi/cli/php_cli.c:1345
#10 0x7f7d44508ec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
#11 0x473ed1 in _start (/root/php-src/php-7.0.2-asan+0x473ed1)
SUMMARY: AddressSanitizer: SEGV /root/php-src/Zend/zend_hash.c:1780 zend_array_dup
==22087== ABORTING
Aborted
When compiled without ASAN, it Segmentation Fault's, and running under gdb gives this:
$ gdb -ex r -ex 'x/i $rip' -ex bt -ex c -ex quit --args ./php-7.0.2-noasan ~/php-crash-7.0-get_defined_vars
<snip>
Starting program: /root/php-src/php-7.0.2-noasan /root/php-crash-7.0-get_defined_vars
Program received signal SIGSEGV, Segmentation fault.
zend_array_dup (source=0x0) at /root/php-src/Zend/zend_hash.c:1780
warning: Source file is more recent than executable.
1780 target->nTableSize = source->nTableSize;
=> 0xe5ea9a <zend_array_dup+90>: mov 0x20(%rbp),%r12d
#0 zend_array_dup (source=0x0) at /root/php-src/Zend/zend_hash.c:1780
#1 0x0000000000e8debd in zif_get_defined_vars (execute_data=<optimized out>, return_value=0x7fffffffd230) at /root/php-src/Zend/zend_builtin_functions.c:1950
#2 0x0000000000d568b3 in zend_call_function (fci=fci@entry=0x7ffff7072000, fci_cache=fci_cache@entry=0x7ffff7072048) at /root/php-src/Zend/zend_execute_API.c:879
#3 0x0000000000e071bb in zend_fcall_info_call (fci=0x7ffff7072000, fcc=0x7ffff7072048, retval_ptr=retval_ptr@entry=0x7fffffffd230, args=args@entry=0x0)
at /root/php-src/Zend/zend_API.c:3574
#4 0x0000000000bbda34 in php_output_handler_op (context=0x7fffffffd260, handler=0x7ffff707f050) at /root/php-src/main/output.c:960
#5 php_output_stack_pop (flags=1) at /root/php-src/main/output.c:1221
#6 php_output_end_all () at /root/php-src/main/output.c:341
#7 0x0000000000b47335 in php_request_shutdown (dummy=dummy@entry=0x0) at /root/php-src/main/main.c:1777
#8 0x00000000011bdb9b in do_cli (argc=2, argv=0x18e38b0) at /root/php-src/sapi/cli/php_cli.c:1142
#9 0x00000000004473b9 in main (argc=2, argv=0x18e38b0) at /root/php-src/sapi/cli/php_cli.c:1345
Continuing.
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=71221&edit=1