Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

php-cli core dump calling a badly formed function #8841

Closed
gjcarrette opened this issue Jun 21, 2022 · 5 comments
Closed

php-cli core dump calling a badly formed function #8841

gjcarrette opened this issue Jun 21, 2022 · 5 comments

Comments

@gjcarrette
Copy link

Description

The following interaction gives a SEGV

$ rpm -q php-cli
php-cli-8.1.4-1.el8.remi.x86_64
$ php -n -dauto_prepend_file= -a
Interactive shell
php > echo phpversion();
8.1.4
php > function f ($x): void { return $x;}
Fatal error: A void function must not return a value in php shell code on line 1
php > f(10);
Segmentation fault (core dumped)

Resulted in this output:

Segmentation fault (core dumped)

But I expected this output instead:

Warning: Uncaught Error: Call to undefined function f() in php shell code:1

Well anything but a core dump.

This happens in PHP 7.4 too so it is not a PHP 8.1 regression.

PHP Version

PHP 8.1.4

Operating System

CentOS Linux release 7.5.1804 (Core)

@cmb69
Copy link
Member

cmb69 commented Jun 21, 2022

Probably relevant:

php > var_dump(function_exists("f"));
bool(false)
php > function f ($x): void { return $x;}

Fatal error: A void function must not return a value in php shell code on line 1
php > var_dump(function_exists("f"));
bool(true)
php >

@cmb69
Copy link
Member

cmb69 commented Jun 23, 2022

Indeed! When a global function is compiled, it is entered in the global function_table early, and is not removed if the compilation fails. That is usually not an issue, but for the interactive mode it is (might also be an issue for the embed SAPI).

alexandre-daubois added a commit to alexandre-daubois/php-src that referenced this issue Jul 6, 2022
alexandre-daubois added a commit to alexandre-daubois/php-src that referenced this issue Jul 6, 2022
alexandre-daubois added a commit to alexandre-daubois/php-src that referenced this issue Jul 6, 2022
alexandre-daubois added a commit to alexandre-daubois/php-src that referenced this issue Jul 7, 2022
alexandre-daubois added a commit to alexandre-daubois/php-src that referenced this issue Jul 8, 2022
alexandre-daubois added a commit to alexandre-daubois/php-src that referenced this issue Jul 8, 2022
alexandre-daubois added a commit to alexandre-daubois/php-src that referenced this issue Jul 8, 2022
@gjcarrette
Copy link
Author

Glad you guys had fun with this one. I thought of this problem generally as one of not making sure that all allocated objects are in some well defined state even in the smallest unit of allocation. It is especially problematic in real-time
garbage collected languages with multiple threads. It is too bad that valgrind does not seem to pick up on this problem at the point of allocation. Here are two tests with valgrind, one with USE_ZEND_ALLOC=0. Now maybe one of the gnu malloc debug options would help detect this at time of allocation, but possibly this kind of check would go too far with PHP.

[webphp-php8gcarrette-dsm1]$ valgrind php -a
==249867== Memcheck, a memory error detector
==249867== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==249867== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==249867== Command: php -a
==249867==
==249867== Warning: set address range perms: large range [0x2415a000, 0x4415a000) (defined)
==249867== Warning: set address range perms: large range [0x59ea1000, 0x79ea1000) (defined)
==249867== Warning: set address range perms: large range [0x59ea1000, 0x79ea1000) (noaccess)
==249867== Warning: set address range perms: large range [0x59ea1000, 0x79ea1000) (defined)
Interactive shell

php > function f($x): void { return $x;}
PHP Fatal error:  A void function must not return a value in php shell code on line 1

Fatal error: A void function must not return a value in php shell code on line 1
php > f(10);
==249867== Jump to the invalid address stated on the next line
==249867==    at 0x6F20736572756769: ???
==249867==  Address 0x6f20736572756769 is not stack'd, malloc'd or (recently) free'd
==249867==
==249867==
==249867== Process terminating with default action of signal 11 (SIGSEGV)
==249867==  Bad permissions for mapped region at address 0x6F20736572756769
==249867==    at 0x6F20736572756769: ???
==249867==
==249867== HEAP SUMMARY:
==249867==     in use at exit: 7,308,710 bytes in 54,023 blocks
==249867==   total heap usage: 90,926 allocs, 36,903 frees, 13,148,235 bytes allocated
==249867==
==249867== LEAK SUMMARY:
==249867==    definitely lost: 39,272 bytes in 1,226 blocks
==249867==    indirectly lost: 40 bytes in 1 blocks
==249867==      possibly lost: 5,496,243 bytes in 42,600 blocks
==249867==    still reachable: 1,773,155 bytes in 10,196 blocks
==249867==         suppressed: 0 bytes in 0 blocks
==249867== Rerun with --leak-check=full to see details of leaked memory
==249867==
==249867== For lists of detected and suppressed errors, rerun with: -s
==249867== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
Segmentation fault (core dumped)

With USE_ZEND_ALLOC=0

php > f(10);
==250881== Use of uninitialised value of size 8
==250881==    at 0x447960: execute_ex (in /usr/bin/php)
==250881==    by 0x447BAB: zend_execute (in /usr/bin/php)
==250881==    by 0x3C8683: zend_eval_stringl (in /usr/bin/php)
==250881==    by 0x2B014D: ??? (in /usr/bin/php)
==250881==    by 0x4BF8F5: ??? (in /usr/bin/php)
==250881==    by 0x2217C2: ??? (in /usr/bin/php)
==250881==    by 0x7F53CA2: (below main) (in /usr/lib64/libc-2.28.so)
==250881==
==250881== Jump to the invalid address stated on the next line
==250881==    at 0x0: ???
==250881==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==250881==
==250881==
==250881== Process terminating with default action of signal 11 (SIGSEGV)
==250881==  Bad permissions for mapped region at address 0x0
==250881==    at 0x0: ???
==250881==

@lucaswerkmeister
Copy link

Another way to create a badly formed function is to use the array append operator in an invalid way:

$ php -a
Interactive shell
php > echo phpversion();
8.1.2
php > function f(){$a[];}
PHP Fatal error:  Cannot use [] for reading in php shell code on line 1
php > f();
Segmentation fault (core dumped)

@bukka
Copy link
Member

bukka commented Sep 8, 2022

From a quick thinking I'd say it should be up to the SAPI to handle this - not sure if there's much point to handle it for all SAPI's if it's irrelevant for them. So labeling that as cli sapi bug.

@bukka bukka added the SAPI: cli label Sep 8, 2022
alexandre-daubois added a commit to alexandre-daubois/php-src that referenced this issue Sep 27, 2022
nielsdos added a commit to nielsdos/php-src that referenced this issue Apr 1, 2023
It's actually not php-cli specific, nor SAPI specific.
We should delay the registration of the function into the function table
until after the compilation was successful, otherwise the function is
mistakingly registered and a NULL dereference will happen when trying to
call it.

I based my test of Nikita's test, so credits to him for the test:
php#8933 (comment)
nielsdos added a commit that referenced this issue Apr 1, 2023
* PHP-8.1:
  Fix GH-10990: mail() throws TypeError after iterating over $additional_headers array by reference
  Fix GH-8841: php-cli core dump calling a badly formed function
nielsdos added a commit that referenced this issue Apr 1, 2023
* PHP-8.2:
  Fix GH-10983: State-dependant segfault in ReflectionObject::getProperties
  Fix GH-10990: mail() throws TypeError after iterating over $additional_headers array by reference
  Fix GH-8841: php-cli core dump calling a badly formed function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants
@bukka @cmb69 @lucaswerkmeister @gjcarrette and others