php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69788 Malformed script causes Uncaught EngineException in php-cgi, valgrind SIGILL
Submitted: 2015-06-09 19:46 UTC Modified: 2015-06-11 21:28 UTC
From: brian dot carpenter at gmail dot com Assigned: nikic (profile)
Status: Closed Package: Reproducible crash
PHP Version: master-Git-2015-06-09 (Git) OS: Debian 7
Private report: No CVE-ID: None
 [2015-06-09 19:46 UTC] brian dot carpenter at gmail dot com
Description:
------------
While fuzzing the latest PHP built from git source with AFL (http://lcamtuf.coredump.cx/afl/), I came across this bug.

geeknik@h9n1:~$ ~/php-src/sapi/cgi/php-cgi -v
PHP 7.0.0-dev (cgi-fcgi) (built: Jun  8 2015 12:00:13)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v3.0.0-dev, Copyright (c) 1998-2015 Zend Technologies

Test script:
---------------
<?0/array(t.array())();

https://www.dropbox.com/s/msw5h4k4qaq2icg/test00-min?dl=0

Expected result:
----------------
PHP v5.4.41-0+deb7u1 (cli) returns the following:

PHP Parse error:  syntax error, unexpected '(' in /home/geeknik/php-tmp/out/fuzzer01/crashes/test00-min on line 1

Actual result:
--------------
Valgrind:

vex amd64->IR: unhandled instruction bytes: 0xF3 0x4D 0xF 0xBC 0xE4 0x45 0x1 0xC4
==18903== valgrind: Unrecognised instruction at address 0x1319a3a.
==18903==    at 0x1319A3A: zend_mm_alloc_pages (zend_alloc.c:483)
==18903==    by 0x131B81C: zend_mm_alloc_small_slow (zend_alloc.c:1190)
==18903==    by 0x155F573: virtual_cwd_startup (zend_virtual_cwd.c:431)
==18903==    by 0x1412DCC: zend_startup (zend.c:640)
==18903==    by 0x11C6F98: php_module_startup (main.c:2066)
==18903==    by 0x181CFCC: php_cgi_startup (cgi_main.c:915)
==18903==    by 0x43B4AC: main (cgi_main.c:1894)
==18903== Your program just tried to execute an instruction that Valgrind
==18903== did not recognise.  There are two possible reasons for this.
==18903== 1. Your program has a bug and erroneously jumped to a non-code
==18903==    location.  If you are running Memcheck and you just saw a
==18903==    warning about a bad jump, it's probably your program's fault.
==18903== 2. The instruction is legitimate but Valgrind doesn't handle it,
==18903==    i.e. it's Valgrind's fault.  If you think this is the case or
==18903==    you are not sure, please let us know and we'll try to fix it.
==18903== Either way, Valgrind will now raise a SIGILL signal which will
==18903== probably kill your program.
==18903== 
==18903== Process terminating with default action of signal 4 (SIGILL)
==18903==  Illegal opcode at address 0x1319A3A
==18903==    at 0x1319A3A: zend_mm_alloc_pages (zend_alloc.c:483)
==18903==    by 0x131B81C: zend_mm_alloc_small_slow (zend_alloc.c:1190)
==18903==    by 0x155F573: virtual_cwd_startup (zend_virtual_cwd.c:431)
==18903==    by 0x1412DCC: zend_startup (zend.c:640)
==18903==    by 0x11C6F98: php_module_startup (main.c:2066)
==18903==    by 0x181CFCC: php_cgi_startup (cgi_main.c:915)
==18903==    by 0x43B4AC: main (cgi_main.c:1894)
Illegal instruction

GDB:

Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
X-Powered-By: PHP/7.0.0-dev
Content-type: text/html; charset=UTF-8

<br />
<b>Fatal error</b>:  Uncaught EngineException: Function name must be a string in /home/geeknik/php-tmp/out/fuzzer01/crashes/test00-min:1
Stack trace:
#0 {main}
  thrown in <b>/home/geeknik/php-tmp/out/fuzzer01/crashes/test00-min</b> on line <b>1</b><br />
[Inferior 1 (process 41744) exited with code 0377]

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-06-09 20:22 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2015-06-09 20:22 UTC] requinix@php.net
The "malformed script" isn't. Not in PHP 7. The Uniform Variable Syntax changes allow it and the code is equivalent to

  $f = array(t . array()); // array("tArray") with notices
  0 / $f();

http://3v4l.org/I5RIC (slightly modified)
https://wiki.php.net/rfc/uniform_variable_syntax

PHP 7 also starts a switch to exceptions instead of errors, which is why you're seeing the EngineException (subject to change) instead of a regular parse error.

https://wiki.php.net/rfc/engine_exceptions_for_php7

That leaves the valgrind problem, but that does seem to be a valgrind problem since PHP does run normally (and under GDB) without problems. Make sure you're using the most recent version of valgrind, but if that doesn't resolve it then I suggest making a bug report there. Remember that PHP 7 is still in development so binaries may/will change.
 [2015-06-10 09:02 UTC] nikic@php.net
-Status: Not a bug +Status: Verified
 [2015-06-10 09:02 UTC] nikic@php.net
I can repro on current master, getting an assertion failure:

php: /home/nikic/php-src/Zend/zend_variables.c:43: _zval_dtor_func: Assertion `((zend_refcounted*)(arr))->refcount <= 1' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff44c2cc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56	../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff44c2cc9 in __GI_raise (sig=sig@entry=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff44c60d8 in __GI_abort () at abort.c:89
#2  0x00007ffff44bbb86 in __assert_fail_base (
    fmt=0x7ffff460c830 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", 
    assertion=assertion@entry=0x1157f60 "((zend_refcounted*)(arr))->refcount <= 1", 
    file=file@entry=0x1157f30 "/home/nikic/php-src/Zend/zend_variables.c", line=line@entry=43, 
    function=function@entry=0x1158050 <__PRETTY_FUNCTION__.9654> "_zval_dtor_func") at assert.c:92
#3  0x00007ffff44bbc32 in __GI___assert_fail (
    assertion=0x1157f60 "((zend_refcounted*)(arr))->refcount <= 1", 
    file=0x1157f30 "/home/nikic/php-src/Zend/zend_variables.c", line=43, 
    function=0x1158050 <__PRETTY_FUNCTION__.9654> "_zval_dtor_func") at assert.c:101
#4  0x0000000000aedfe0 in _zval_dtor_func (p=0x7fffee6587e0, 
    __zend_filename=0x1157378 "/home/nikic/php-src/Zend/zend_operators.c", __zend_lineno=519)
    at /home/nikic/php-src/Zend/zend_variables.c:43
#5  0x0000000000adfef2 in _zval_dtor (zvalue=0x7fffffff9d08, 
    __zend_filename=0x1157378 "/home/nikic/php-src/Zend/zend_operators.c", __zend_lineno=519)
    at /home/nikic/php-src/Zend/zend_variables.h:43
#6  0x0000000000ae16f1 in _convert_to_string (op=0x7fffffff9d08, 
    __zend_filename=0x1152b40 "/home/nikic/php-src/Zend/zend_compile.c", __zend_lineno=5732)
    at /home/nikic/php-src/Zend/zend_operators.c:519
#7  0x0000000000accd34 in zend_compile_binary_op (result=0x7fffffff9dd0, ast=0x7fffee67b0b8)
    at /home/nikic/php-src/Zend/zend_compile.c:5732
#8  0x0000000000ad125b in zend_compile_expr (result=0x7fffffff9dd0, ast=0x7fffee67b0b8)
    at /home/nikic/php-src/Zend/zend_compile.c:6913
#9  0x0000000000aceae7 in zend_compile_array (result=0x7fffffff9ef0, ast=0x7fffee67b0e8)
    at /home/nikic/php-src/Zend/zend_compile.c:6260
#10 0x0000000000ad1423 in zend_compile_expr (result=0x7fffffff9ef0, ast=0x7fffee67b0e8)
    at /home/nikic/php-src/Zend/zend_compile.c:6976
#11 0x0000000000ac2e6b in zend_compile_call (result=0x7fffffffa000, ast=0x7fffee67b148, type=0)
    at /home/nikic/php-src/Zend/zend_compile.c:3159
#12 0x0000000000ad15b5 in zend_compile_var (result=0x7fffffffa000, ast=0x7fffee67b148, type=0)
    at /home/nikic/php-src/Zend/zend_compile.c:7015
#13 0x0000000000ad11cb in zend_compile_expr (result=0x7fffffffa000, ast=0x7fffee67b148)
    at /home/nikic/php-src/Zend/zend_compile.c:6895
#14 0x0000000000acca83 in zend_compile_binary_op (result=0x7fffffffa090, ast=0x7fffee67b160)
    at /home/nikic/php-src/Zend/zend_compile.c:5673
#15 0x0000000000ad125b in zend_compile_expr (result=0x7fffffffa090, ast=0x7fffee67b160)
    at /home/nikic/php-src/Zend/zend_compile.c:6913
#16 0x0000000000ad0e68 in zend_compile_stmt (ast=0x7fffee67b160)
    at /home/nikic/php-src/Zend/zend_compile.c:6864
#17 0x0000000000ad0a21 in zend_compile_top_stmt (ast=0x7fffee67b160)
    at /home/nikic/php-src/Zend/zend_compile.c:6754
#18 0x0000000000ad0a00 in zend_compile_top_stmt (ast=0x7fffee67b018)
    at /home/nikic/php-src/Zend/zend_compile.c:6749
#19 0x0000000000a773ce in compile_file (file_handle=0x7fffffffc9c0, type=8)
...
 [2015-06-10 09:12 UTC] nikic@php.net
-Assigned To: +Assigned To: nikic
 [2015-06-10 09:12 UTC] nikic@php.net
The problem are the string conversions here: http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_compile.c#5727 At this point the RHS array() has rc=2 due to the way constexprs are evaluated, so we end up dtoring a live array there.

I would suggest to just switch the dtor to a ptr_dtor in convert_to_string and all similar functions and essentially make it save to use convert_to_string without prior separation - doesn't really cost us anything and will avoid any kind of trouble of this sort in the future.
 [2015-06-11 21:28 UTC] nikic@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 03:01:27 2024 UTC