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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: brian dot carpenter at gmail dot com
New email:
PHP Version: OS:

 

 [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 10:01:28 2024 UTC