php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71221 Null pointer deref (segfault) in get_defined_vars via ob_start
Submitted: 2015-12-25 20:14 UTC Modified: 2015-12-26 04:54 UTC
From: hugh at allthethings dot co dot nz Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 7.0.1 OS: Linux
Private report: No CVE-ID:
 [2015-12-25 20:14 UTC] 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.



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-12-26 04:33 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
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-26 04:33 UTC] laruence@php.net
-Status: Open +Status: Closed
 [2015-12-26 04:54 UTC] hugh at allthethings dot co dot nz
Thanks for the quick fix! Will there be a cve issued for this?
 [2016-07-20 11:34 UTC] davey@php.net
Automatic comment on behalf of laruence@gmail.com
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)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sat Apr 29 07:01:45 2017 UTC