Skip to content

Commit

Permalink
Fix #97836 and #81705: Segfault / type confusion in concat_function
Browse files Browse the repository at this point in the history
The following sequence of actions was happening which caused a null
pointer dereference:
1. debug_backtrace() returns an array
2. The concatenation to $c will transform the array to a string via
   `zval_get_string_func` for op2 and output a warning.
   Note that zval op1 is of type string due to the first do-while
   sequence.
3. The warning of an implicit "array to string conversion" triggers
   the ob_start callback to run. This code transform $c (==op1) to a long.
4. The code below the 2 do-while sequences assume that both op1 and op2
   are strings, but this is no longer the case. A dereference of the
   string will therefore result in a null pointer dereference.

The solution used here is to work with the zend_string directly instead
of with the ops.

For the tests:
Co-authored-by: changochen1@gmail.com
Co-authored-by: cmbecker69@gmx.de
Co-authored-by: yukik@risec.co.jp

Closes GH-10049.
  • Loading branch information
nielsdos committed May 16, 2023
1 parent 7914b8c commit 727e26f
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 40 deletions.
3 changes: 3 additions & 0 deletions NEWS
Expand Up @@ -37,6 +37,9 @@ PHP NEWS
index). (ColinHDev)
. Fix bug GH-8846 (Implement delayed early binding for classes without
parents). (ilutov)
. Fix bug #79836 (Segfault in concat_function). (nielsdos)
. Fix bug #81705 (type confusion/UAF on set_error_handler with concat
operation). (nielsdos)

- Date:
. Implement More Appropriate Date/Time Exceptions RFC. (Derick)
Expand Down
18 changes: 18 additions & 0 deletions Zend/tests/bug79836.phpt
@@ -0,0 +1,18 @@
--TEST--
Bug #79836 (Segfault in concat_function)
--INI--
opcache.optimization_level = 0x7FFEBFFF & ~0x400
--FILE--
<?php
$counter = 0;
ob_start(function ($buffer) use (&$c, &$counter) {
$c = 0;
++$counter;
}, 1);
$c .= [];
$c .= [];
ob_end_clean();
echo $counter . "\n";
?>
--EXPECT--
3
18 changes: 18 additions & 0 deletions Zend/tests/bug79836_1.phpt
@@ -0,0 +1,18 @@
--TEST--
Bug #79836 (Segfault in concat_function)
--INI--
opcache.optimization_level = 0x7FFEBFFF & ~0x400
--FILE--
<?php
$x = 'non-empty';
ob_start(function () use (&$c) {
$c = 0;
}, 1);
$c = [];
$x = $c . $x;
$x = $c . $x;
ob_end_clean();
echo "Done\n";
?>
--EXPECT--
Done
25 changes: 25 additions & 0 deletions Zend/tests/bug79836_2.phpt
@@ -0,0 +1,25 @@
--TEST--
Bug #79836 (Segfault in concat_function)
--FILE--
<?php
$c = str_repeat("abcd", 10);

ob_start(function () use (&$c) {
$c = 0;
}, 1);

class X {
function __toString() {
echo "a";
return "abc";
}
}

$xxx = new X;

$x = $c . $xxx;
ob_end_clean();
echo $x . "\n";
?>
--EXPECT--
abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabc
19 changes: 19 additions & 0 deletions Zend/tests/bug81705.phpt
@@ -0,0 +1,19 @@
--TEST--
Bug #81705 (type confusion/UAF on set_error_handler with concat operation)
--FILE--
<?php

$arr = [0];
$my_var = str_repeat("a", 1);
set_error_handler(
function() use(&$my_var) {
echo("error\n");
$my_var = 0x123;
}
);
$my_var .= $GLOBALS["arr"];
var_dump($my_var);
?>
--EXPECT--
error
string(6) "aArray"
21 changes: 21 additions & 0 deletions Zend/tests/class_toString_concat_non_interned_with_itself.phpt
@@ -0,0 +1,21 @@
--TEST--
Test concatenating a class instance that has __toString with itself that uses a non-interned string
--FILE--
<?php
$global_non_interned_string = str_repeat("a", 3);

class Test {
public function __toString() {
global $global_non_interned_string;
return $global_non_interned_string;
}
}

$test1 = new Test;
$test2 = new Test;
$test1 .= $test2;

echo $test1 . "\n";
?>
--EXPECT--
aaaaaa
16 changes: 16 additions & 0 deletions Zend/tests/class_toString_concat_with_itself.phpt
@@ -0,0 +1,16 @@
--TEST--
Test concatenating a class instance that has __toString with itself
--FILE--
<?php
class Tmp {
public function __toString() {
return "abc";
}
}

$tmp = new Tmp;
$tmp .= $tmp;
echo $tmp . "\n";
?>
--EXPECT--
abcabc
118 changes: 78 additions & 40 deletions Zend/zend_operators.c
Expand Up @@ -1940,108 +1940,146 @@ ZEND_API zend_result ZEND_FASTCALL shift_right_function(zval *result, zval *op1,
ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
zval *orig_op1 = op1;
zval op1_copy, op2_copy;

ZVAL_UNDEF(&op1_copy);
ZVAL_UNDEF(&op2_copy);
zend_string *op1_string, *op2_string;
bool free_op1_string = false;
bool free_op2_string = false;

do {
if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) {
if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
op1_string = Z_STR_P(op1);
} else {
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
if (Z_TYPE_P(op1) == IS_STRING) break;
if (Z_TYPE_P(op1) == IS_STRING) {
op1_string = Z_STR_P(op1);
break;
}
}
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT);
ZVAL_STR(&op1_copy, zval_get_string_func(op1));
op1_string = zval_get_string_func(op1);
if (UNEXPECTED(EG(exception))) {
zval_ptr_dtor_str(&op1_copy);
zend_string_release(op1_string);
if (orig_op1 != result) {
ZVAL_UNDEF(result);
}
return FAILURE;
}
free_op1_string = true;
if (result == op1) {
if (UNEXPECTED(op1 == op2)) {
op2 = &op1_copy;
op2_string = op1_string;
goto has_op2_string;
}
}
op1 = &op1_copy;
}
} while (0);
do {
if (UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) {
if (Z_ISREF_P(op2)) {
op2 = Z_REFVAL_P(op2);
if (Z_TYPE_P(op2) == IS_STRING) break;
}
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
op2_string = Z_STR_P(op2);
} else {
if (Z_ISREF_P(op2)) {
op2 = Z_REFVAL_P(op2);
if (Z_TYPE_P(op2) == IS_STRING) {
op2_string = Z_STR_P(op2);
break;
}
}
/* hold an additional reference because a userland function could free this */
if (!free_op1_string) {
op1_string = zend_string_copy(op1_string);
free_op1_string = true;
}
ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_CONCAT);
ZVAL_STR(&op2_copy, zval_get_string_func(op2));
op2_string = zval_get_string_func(op2);
if (UNEXPECTED(EG(exception))) {
zval_ptr_dtor_str(&op1_copy);
zval_ptr_dtor_str(&op2_copy);
zend_string_release(op1_string);
zend_string_release(op2_string);
if (orig_op1 != result) {
ZVAL_UNDEF(result);
}
return FAILURE;
}
op2 = &op2_copy;
free_op2_string = true;
}
} while (0);

if (UNEXPECTED(Z_STRLEN_P(op1) == 0)) {
if (EXPECTED(result != op2)) {
has_op2_string:;
if (UNEXPECTED(ZSTR_LEN(op1_string) == 0)) {
if (EXPECTED(free_op2_string || result != op2)) {
if (result == orig_op1) {
i_zval_ptr_dtor(result);
}
ZVAL_COPY(result, op2);
if (free_op2_string) {
/* transfer ownership of op2_string */
ZVAL_STR(result, op2_string);
free_op2_string = false;
} else {
ZVAL_STR_COPY(result, op2_string);
}
}
} else if (UNEXPECTED(Z_STRLEN_P(op2) == 0)) {
if (EXPECTED(result != op1)) {
} else if (UNEXPECTED(ZSTR_LEN(op2_string) == 0)) {
if (EXPECTED(free_op1_string || result != op1)) {
if (result == orig_op1) {
i_zval_ptr_dtor(result);
}
ZVAL_COPY(result, op1);
if (free_op1_string) {
/* transfer ownership of op1_string */
ZVAL_STR(result, op1_string);
free_op1_string = false;
} else {
ZVAL_STR_COPY(result, op1_string);
}
}
} else {
size_t op1_len = Z_STRLEN_P(op1);
size_t op2_len = Z_STRLEN_P(op2);
size_t op1_len = ZSTR_LEN(op1_string);
size_t op2_len = ZSTR_LEN(op2_string);
size_t result_len = op1_len + op2_len;
zend_string *result_str;
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(Z_STR_P(op1), Z_STR_P(op2));
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_string, op2_string);

if (UNEXPECTED(op1_len > ZSTR_MAX_LEN - op2_len)) {
if (free_op1_string) zend_string_release(op1_string);
if (free_op2_string) zend_string_release(op2_string);
zend_throw_error(NULL, "String size overflow");
zval_ptr_dtor_str(&op1_copy);
zval_ptr_dtor_str(&op2_copy);
if (orig_op1 != result) {
ZVAL_UNDEF(result);
}
return FAILURE;
}

if (result == op1 && Z_REFCOUNTED_P(result)) {
if (result == op1) {
if (free_op1_string) {
/* op1_string will be used as the result, so we should not free it */
i_zval_ptr_dtor(result);
free_op1_string = false;
}
/* special case, perform operations on result */
result_str = zend_string_extend(Z_STR_P(result), result_len, 0);
result_str = zend_string_extend(op1_string, result_len, 0);
/* account for the case where result_str == op1_string == op2_string and the realloc is done */
if (op1_string == op2_string) {
if (free_op2_string) {
zend_string_release(op2_string);
free_op2_string = false;
}
op2_string = result_str;
}
} else {
result_str = zend_string_alloc(result_len, 0);
memcpy(ZSTR_VAL(result_str), Z_STRVAL_P(op1), op1_len);
memcpy(ZSTR_VAL(result_str), ZSTR_VAL(op1_string), op1_len);
if (result == orig_op1) {
i_zval_ptr_dtor(result);
}
}
GC_ADD_FLAGS(result_str, flags);

/* This has to happen first to account for the cases where result == op1 == op2 and
* the realloc is done. In this case this line will also update Z_STRVAL_P(op2) to
* point to the new string. The first op2_len bytes of result will still be the same. */
ZVAL_NEW_STR(result, result_str);

memcpy(ZSTR_VAL(result_str) + op1_len, Z_STRVAL_P(op2), op2_len);
memcpy(ZSTR_VAL(result_str) + op1_len, ZSTR_VAL(op2_string), op2_len);
ZSTR_VAL(result_str)[result_len] = '\0';
}

zval_ptr_dtor_str(&op1_copy);
zval_ptr_dtor_str(&op2_copy);
if (free_op1_string) zend_string_release(op1_string);
if (free_op2_string) zend_string_release(op2_string);

return SUCCESS;
}
/* }}} */
Expand Down

5 comments on commit 727e26f

@dstogov
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this commit may lead to incorrect behavior. Produce non-string return value.

php -r '$a = false; $a .= $a; var_dump($a);'

This may cause the followingviolation of the type inference and the following crash in JIT.
See oss-fuzz #59184

<?php
function test() {
    for ($i = 1; $i < 3; $i++) {
        $a .= $c .= ! $a .= $a;
        $a = $a = $a-- * +$b != $a;
    }
}
test();
?>

@dstogov
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another problem caused by the same patch is 59072
The following script casuses use-after-free after a memory overflow

<?php
$a=[3,2,"",2,0,3,1,0,4,5,0];
foreach($a as $y) {
    $i.=$ti.=$ti2.=$d=$e.=$ti.=$ti2.=$time.='ÿÿÿ ÿ    ';
    try {
        new DateTime($time,$t);
    } catch(ExcEption$e) {
    }
}
$ USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1 sapi/cli/php -n ~/tmp/fuzz-59072.php

Warning: Undefined variable $time in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $ti2 in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $ti in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $e in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $i in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Fatal error: Allowed memory size of 134217728 bytes exhausted at file:0 (tried to allocate 41924224 bytes) in /home/dmitry/tmp/fuzz-59072.php on line 4
=================================================================
==478827==ERROR: AddressSanitizer: heap-use-after-free on address 0x60e0000096c0 at pc 0x000001fce668 bp 0x7ffece0d37d0 sp 0x7ffece0d37c8
READ of size 4 at 0x60e0000096c0 thread T0
    #0 0x1fce667 in zend_gc_refcount /home/dmitry/php/php-master/Zend/zend_types.h:1252
    #1 0x1fcea55 in zval_refcount_p /home/dmitry/php/php-master/Zend/zend_types.h:1301
    #2 0x1fd4303 in zval_call_destructor /home/dmitry/php/php-master/Zend/zend_execute_API.c:215
    #3 0x20c845e in zend_hash_reverse_apply /home/dmitry/php/php-master/Zend/zend_hash.c:2169
    #4 0x1fd4850 in shutdown_destructors /home/dmitry/php/php-master/Zend/zend_execute_API.c:260
    #5 0x204aa6d in zend_call_destructors /home/dmitry/php/php-master/Zend/zend.c:1262
    #6 0x1dd5354 in php_request_shutdown /home/dmitry/php/php-master/main/main.c:1826
    #7 0x27cebac in do_cli /home/dmitry/php/php-master/sapi/cli/php_cli.c:1130
    #8 0x27cfa21 in main /home/dmitry/php/php-master/sapi/cli/php_cli.c:1328
    #9 0x7f781ee4a50f in __libc_start_call_main (/usr/lib64/../lib64/libc.so.6+0x2750f)
    #10 0x7f781ee4a5c8 in __libc_start_main@GLIBC_2.2.5 (/usr/lib64/../lib64/libc.so.6+0x275c8)
    #11 0x6086f4 in _start (/home/dmitry/php/php-master/CGI-DEBUG-64/sapi/cli/php+0x6086f4)

0x60e0000096c0 is located 0 bytes inside of 152-byte region [0x60e0000096c0,0x60e000009758)
freed by thread T0 here:
    #0 0x7f7822cb9388 in __interceptor_free.part.0 (/usr/lib64/../lib64/libasan.so.8+0xb9388)
    #1 0x1f3aafc in tracked_free /home/dmitry/php/php-master/Zend/zend_alloc.c:2848
    #2 0x1f38cfa in _efree_custom /home/dmitry/php/php-master/Zend/zend_alloc.c:2483
    #3 0x1f39013 in _efree /home/dmitry/php/php-master/Zend/zend_alloc.c:2603
    #4 0x25160e1 in zend_objects_store_del /home/dmitry/php/php-master/Zend/zend_objects_API.c:204
    #5 0x203fb79 in rc_dtor_func /home/dmitry/php/php-master/Zend/zend_variables.c:57
    #6 0x20092a6 in i_zval_ptr_dtor /home/dmitry/php/php-master/Zend/zend_variables.h:44
    #7 0x2028399 in concat_function /home/dmitry/php/php-master/Zend/zend_operators.c:2053
    #8 0x212b68b in zend_binary_op /home/dmitry/php/php-master/Zend/zend_execute.c:1557
    #9 0x23b65a6 in ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDLER /home/dmitry/php/php-master/Zend/zend_vm_execute.h:45102
    #10 0x242f053 in execute_ex /home/dmitry/php/php-master/Zend/zend_vm_execute.h:60792
    #11 0x2432a64 in zend_execute /home/dmitry/php/php-master/Zend/zend_vm_execute.h:61397
    #12 0x20510a3 in zend_execute_scripts /home/dmitry/php/php-master/Zend/zend.c:1836
    #13 0x1dd8f30 in php_execute_script /home/dmitry/php/php-master/main/main.c:2482
    #14 0x27cd3c4 in do_cli /home/dmitry/php/php-master/sapi/cli/php_cli.c:959
    #15 0x27cfa21 in main /home/dmitry/php/php-master/sapi/cli/php_cli.c:1328
    #16 0x7f781ee4a50f in __libc_start_call_main (/usr/lib64/../lib64/libc.so.6+0x2750f)

previously allocated by thread T0 here:
    #0 0x7f7822cba6af in __interceptor_malloc (/usr/lib64/../lib64/libasan.so.8+0xba6af)
    #1 0x1f3a830 in tracked_malloc /home/dmitry/php/php-master/Zend/zend_alloc.c:2829
    #2 0x1f38b68 in _malloc_custom /home/dmitry/php/php-master/Zend/zend_alloc.c:2474
    #3 0x1f38f46 in _emalloc /home/dmitry/php/php-master/Zend/zend_alloc.c:2593
    #4 0x24f0c0f in zend_objects_new /home/dmitry/php/php-master/Zend/zend_objects.c:187
    #5 0x245c0d8 in zend_default_exception_new /home/dmitry/php/php-master/Zend/zend_exceptions.c:251
    #6 0x206dc1c in _object_and_properties_init /home/dmitry/php/php-master/Zend/zend_API.c:1760
    #7 0x206dd4a in object_init_ex /home/dmitry/php/php-master/Zend/zend_API.c:1774
    #8 0x2466f32 in zend_throw_exception_zstr /home/dmitry/php/php-master/Zend/zend_exceptions.c:818
    #9 0x24674c1 in zend_throw_exception /home/dmitry/php/php-master/Zend/zend_exceptions.c:838
    #10 0x2467642 in zend_throw_exception_ex /home/dmitry/php/php-master/Zend/zend_exceptions.c:855
    #11 0x631687 in php_date_initialize /home/dmitry/php/php-master/ext/date/php_date.c:2410
    #12 0x6353ce in zim_DateTime___construct /home/dmitry/php/php-master/ext/date/php_date.c:2588
    #13 0x217261a in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /home/dmitry/php/php-master/Zend/zend_vm_execute.h:1867
    #14 0x2417287 in execute_ex /home/dmitry/php/php-master/Zend/zend_vm_execute.h:57053
    #15 0x2432a64 in zend_execute /home/dmitry/php/php-master/Zend/zend_vm_execute.h:61397
    #16 0x20510a3 in zend_execute_scripts /home/dmitry/php/php-master/Zend/zend.c:1836
    #17 0x1dd8f30 in php_execute_script /home/dmitry/php/php-master/main/main.c:2482
    #18 0x27cd3c4 in do_cli /home/dmitry/php/php-master/sapi/cli/php_cli.c:959
    #19 0x27cfa21 in main /home/dmitry/php/php-master/sapi/cli/php_cli.c:1328
    #20 0x7f781ee4a50f in __libc_start_call_main (/usr/lib64/../lib64/libc.so.6+0x2750f)
$ USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1 gdb --args sapi/cli/php -n ~/tmp/fuzz-59072.php
GNU gdb (GDB) Fedora Linux 13.1-3.fc37
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from sapi/cli/php...
(gdb) b zend_error_noreturn 
Breakpoint 1 at 0x204eef0: file /home/dmitry/php/php-master/Zend/zend.c, line 1632.
(gdb) r
Starting program: /home/dmitry/php/php-master/CGI-DEBUG-64/sapi/cli/php -n /home/dmitry/tmp/fuzz-59072.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Warning: Undefined variable $time in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $ti2 in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $ti in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $e in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $i in /home/dmitry/tmp/fuzz-59072.php on line 4

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Warning: Undefined variable $t in /home/dmitry/tmp/fuzz-59072.php on line 6

Breakpoint 1, zend_error_noreturn (type=1, format=0x3aa4d60 "Allowed memory size of %zu bytes exhausted at %s:%d (tried to allocate %zu bytes)")
    at /home/dmitry/php/php-master/Zend/zend.c:1632
1632		get_filename_lineno(type, &filename, &lineno);
Missing separate debuginfos, use: dnf debuginfo-install aspell-0.60.8-10.fc37.x86_64 bzip2-libs-1.0.8-12.fc37.x86_64 cyrus-sasl-lib-2.1.28-8.fc37.x86_64 freetype-2.12.1-3.fc37.x86_64 glib2-2.74.7-1.fc37.x86_64 glibc-2.36-9.fc37.x86_64 gmp-6.2.1-3.fc37.x86_64 graphite2-1.3.14-10.fc37.x86_64 harfbuzz-5.2.0-1.fc37.x86_64 keyutils-libs-1.6.1-5.fc37.x86_64 krb5-libs-1.19.2-13.fc37.x86_64 libX11-1.8.4-1.fc37.x86_64 libXau-1.0.10-1.fc37.x86_64 libXpm-3.5.15-2.fc37.x86_64 libasan-12.3.1-1.fc37.x86_64 libbrotli-1.0.9-9.fc37.x86_64 libcom_err-1.46.5-3.fc37.x86_64 libcurl-7.85.0-8.fc37.x86_64 libevent-2.1.12-7.fc37.x86_64 libffi-3.4.4-1.fc37.x86_64 libgcc-12.3.1-1.fc37.x86_64 libicu-71.1-2.fc37.x86_64 libidn2-2.3.4-1.fc37.x86_64 libjpeg-turbo-2.1.3-2.fc37.x86_64 libnghttp2-1.51.0-1.fc37.x86_64 libpng-1.6.37-13.fc37.x86_64 libpsl-0.21.1-6.fc37.x86_64 libselinux-3.5-1.fc37.x86_64 libssh-0.10.4-2.fc37.x86_64 libstdc++-12.3.1-1.fc37.x86_64 libubsan-12.3.1-1.fc37.x86_64 libunistring-1.0-2.fc37.x86_64 libxcb-1.13.1-10.fc37.x86_64 libxcrypt-4.4.33-4.fc37.x86_64 libxml2-2.10.4-1.fc37.x86_64 libzip-1.9.2-2.fc37.x86_64 libzstd-1.5.5-1.fc37.x86_64 oniguruma-6.9.8-2.D20220919gitb041f6d.fc37.x86_64 openldap-2.6.4-1.fc37.x86_64 pcre2-10.40-1.fc37.1.x86_64 sqlite-libs-3.40.0-1.fc37.x86_64 unixODBC-2.3.11-1.fc37.x86_64 xz-libs-5.4.1-1.fc37.x86_64
(gdb) bt
#0  zend_error_noreturn (type=1, format=0x3aa4d60 "Allowed memory size of %zu bytes exhausted at %s:%d (tried to allocate %zu bytes)")
    at /home/dmitry/php/php-master/Zend/zend.c:1632
#1  0x0000000001f23c01 in zend_mm_safe_error (heap=0x614000000040, 
    format=0x3aa4d60 "Allowed memory size of %zu bytes exhausted at %s:%d (tried to allocate %zu bytes)", limit=134217728, filename=0x3aa5280 "file", 
    lineno=0, size=41924224) at /home/dmitry/php/php-master/Zend/zend_alloc.c:383
#2  0x0000000001f3a7f3 in tracked_check_limit (heap=0x614000000040, add_size=41924224) at /home/dmitry/php/php-master/Zend/zend_alloc.c:2813
#3  0x0000000001f3abc3 in tracked_realloc (ptr=0x614000001240, new_size=41924616) at /home/dmitry/php/php-master/Zend/zend_alloc.c:2861
#4  0x0000000001f38ea4 in _realloc_custom (ptr=0x614000001240, size=41924616, __zend_filename=0x3aee3a0 "/home/dmitry/php/php-master/Zend/zend_string.h", 
    __zend_lineno=271, __zend_orig_filename=0x0, __zend_orig_lineno=0) at /home/dmitry/php/php-master/Zend/zend_alloc.c:2492
#5  0x0000000001f390ed in _erealloc (ptr=0x614000001240, size=41924616, __zend_filename=0x3aee3a0 "/home/dmitry/php/php-master/Zend/zend_string.h", 
    __zend_lineno=271, __zend_orig_filename=0x0, __zend_orig_lineno=0) at /home/dmitry/php/php-master/Zend/zend_alloc.c:2614
#6  0x000000000200849a in zend_string_extend (s=0x614000001240, len=41924589, persistent=false) at /home/dmitry/php/php-master/Zend/zend_string.h:271
#7  0x00000000020283bc in concat_function (result=0x7fffe3c4e8d0, op1=0x7fffe3c4e8d0, op2=0x7fffe3c4e940)
    at /home/dmitry/php/php-master/Zend/zend_operators.c:2057
#8  0x000000000212b68c in zend_binary_op (ret=0x7fffe3c4e8d0, op1=0x7fffe3c4e8d0, op2=0x7fffe3c4e940) at /home/dmitry/php/php-master/Zend/zend_execute.c:1557
#9  0x00000000023b65a7 in ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDLER () at /home/dmitry/php/php-master/Zend/zend_vm_execute.h:45102
#10 0x000000000242f054 in execute_ex (ex=0x7fffe3c4e820) at /home/dmitry/php/php-master/Zend/zend_vm_execute.h:60792
#11 0x0000000002432a65 in zend_execute (op_array=0x6110000075c0, return_value=0x0) at /home/dmitry/php/php-master/Zend/zend_vm_execute.h:61397
#12 0x00000000020510a4 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/dmitry/php/php-master/Zend/zend.c:1836
#13 0x0000000001dd8f31 in php_execute_script (primary_file=0x7fffffffc890) at /home/dmitry/php/php-master/main/main.c:2482
#14 0x00000000027cd3c5 in do_cli (argc=3, argv=0x6030000006d0) at /home/dmitry/php/php-master/sapi/cli/php_cli.c:959
#15 0x00000000027cfa22 in main (argc=3, argv=0x6030000006d0) at /home/dmitry/php/php-master/sapi/cli/php_cli.c:1328

@dstogov
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iluuu1994
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dstogov Thanks, I'll have a look.

@iHeadRu
Copy link

@iHeadRu iHeadRu commented on 727e26f Jun 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, There is exploit based on this bug, which works on versions PHP 8.0.29, 8.1.20 and already unsupported 7.3.33, 7.4.33:
https://raw.githubusercontent.com/mm0r1/exploits/master/php-concat-bypass/exploit.php
How it could be fixed?

Please sign in to comment.