Bug #72146 [Ver->Csd]: Integer overflow on substr_replace

From: Date: Thu, 15 Jul 2021 10:58:24 +0000
Subject: Bug #72146 [Ver->Csd]: Integer overflow on substr_replace
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-235045@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=72146&edit=1

 ID:                 72146
 Updated by:         git@php.net
 Reported by:        fernando at null-life dot com
 Summary:            Integer overflow on substr_replace
-Status:             Verified
+Status:             Closed
 Type:               Bug
 Package:            Strings related
 Operating System:   Linux
 PHP Version:        5.6.21
 Assigned To:        cmb
 Block user comment: N
 Private report:     N

 New Comment:

Automatic comment on behalf of cmb69
Revision: https://github.com/php/php-src/commit/33f8dfb15a34893d8311683db69ea857e66b8c90
Log: Fix #72146: Integer overflow on substr_replace


Previous Comments:
------------------------------------------------------------------------
[2021-07-14 15:22:30] cmb@php.net

The following pull request has been associated:

Patch Name: Fix #72146: Integer overflow on substr_replace
On GitHub:  https://github.com/php/php-src/pull/7240
Patch:      https://github.com/php/php-src/pull/7240.patch

------------------------------------------------------------------------
[2016-12-07 18:41:06] fernando at null-life dot com

This issue (or a similar one) also affects PHP 7.1, keeps popping up on my server.

------------------------------------------------------------------------
[2016-05-13 02:18:03] stas@php.net

Doesn't look like security issue. May be size_t/int confusion again.

------------------------------------------------------------------------
[2016-05-03 19:06:29] fernando at null-life dot com

Description:
------------
This was tested on a 32 bits build with ASAN enabled.

Supplying len as the MAX_INT value on substr_replace is able to evade some checks on the code and
generates an integer overflow calculating offsets during memcpy calls.

The memcpy in line 2580  ext/standard/string.c seems to be the guilty one:

memcpy(result, Z_STRVAL_P(orig_str), f);
memcpy((result + f), Z_STRVAL_PP(repl), Z_STRLEN_PP(repl));
memcpy((result + f + Z_STRLEN_PP(repl)), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f -
l); 

l is the MAX_INT value and when added with f and orig_str length it will generate a negative offset
(overflow)

After setting a bp on that memcpy and checking the stack you can see that orig_str points to
0xf5986ac0, after calculating the offset adding f and l it will start pointing to 0x75986ac2 (src
memcpy). 

The 0x80000003  value on the stack is also a negative value that becomes a huge one when used inside
memcpy since it expects an unsigned value (size memcpy)

Reading symbols from /home/user/php/php56dbg/sapi/cli/php...done.
(gdb) b *0x838d9fa
Breakpoint 1 at 0x838d9fa: file /home/user/php/php56dbg/ext/standard/string.c, line 2580.
(gdb) r substr-rep.php
Starting program: /home/user/php/php56dbg/sapi/cli/php substr-rep.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".

Breakpoint 1, 0x0838d9fa in zif_substr_replace (ht=4, return_value=0xf5a8b9e8,
return_value_ptr=0xf5a700f4, this_ptr=0x0, return_value_used=0) at
/home/user/php/php56dbg/ext/standard/string.c:2580
2580                                    memcpy((result + f + Z_STRLEN_PP(repl)),
Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l);
(gdb) x/20x $esp
0xffff9f80:     0x7570403e      0x75986ac2      0x80000003      0x00000983
0xffff9f90:     0x08b47438      0x00000000      0xf5a700f4      0xf5a8b9e8
0xffff9fa0:     0xf5a701c8      0xf5a701d0      0xf5a701d4      0xf5a701cc
0xffff9fb0:     0xf5a8b7d8      0x00000009      0xffff9fe8      0x0845335b
0xffff9fc0:     0xf5a8b7e4      0x00000000      0x00000000      0x00000000
(gdb) p l
$1 = 2147483647
(gdb) p *orig_str
$6 = {value = {lval = -174560576, dval = 1.2645730362071774e-313, str = {val = 0xf5986ac0
"ABCDE", len = 5}, ht = 0xf5986ac0, obj = {handle = 4120406720, handlers = 0x5}, ast =
0xf5986ac0}, refcount__gc = 1, type = 6 '\006',
  is_ref__gc = 0 '\000'}


Test script:
---------------
<?php
ini_set('memory_limit', -1);

$var1=["ABCDE"];
$var2="123";
$var3=3;
$var4=2147483647; // int max

substr_replace($var1, $var2, $var3, $var4);

Expected result:
----------------
No crash

Actual result:
--------------
=================================================================
==20971==ERROR: AddressSanitizer: memcpy-param-overlap: memory ranges [0x70cbf836,0xf0cbf839) and
[0x725192ba, 0xf25192bd) overlap
    #0 0xf72a28ca in __asan_memcpy (/usr/lib/i386-linux-gnu/libasan.so.2+0x8a8ca)
    #1 0xf72a2c2f in memcpy (/usr/lib/i386-linux-gnu/libasan.so.2+0x8ac2f)
    #2 0x90973f1 in memcpy /usr/include/i386-linux-gnu/bits/string3.h:53
    #3 0x90973f1 in zif_substr_replace /ramdisk/php-56/ext/standard/string.c:2580
    #4 0x9a62ed1 in zend_do_fcall_common_helper_SPEC /ramdisk/php-56/Zend/zend_vm_execute.h:558
    #5 0x98cfa0f in execute_ex /ramdisk/php-56/Zend/zend_vm_execute.h:363
    #6 0x9a57204 in zend_execute /ramdisk/php-56/Zend/zend_vm_execute.h:388
    #7 0x95b24b1 in zend_execute_scripts /ramdisk/php-56/Zend/zend.c:1341
    #8 0x92d8f4b in php_execute_script /ramdisk/php-56/main/main.c:2613
    #9 0x9a6c4c9 in do_cli /ramdisk/php-56/sapi/cli/php_cli.c:994
    #10 0x808e5b4 in main /ramdisk/php-56/sapi/cli/php_cli.c:1378
    #11 0xf6aba636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
    #12 0x808eb6a  (/ramdisk/php-56/sapi/cli/php+0x808eb6a)

0x70cbf836 is located 54 bytes inside of 2147745792-byte region [0x70cbf800,0xf0cff800)
allocated by thread T0 here:
    #0 0xf72aed06 in malloc (/usr/lib/i386-linux-gnu/libasan.so.2+0x96d06)
    #1 0x941fcb7 in zend_mm_mem_malloc_alloc /ramdisk/php-56/Zend/zend_alloc.c:287

0xf0cff800 is located 0 bytes to the right of 2147745792-byte region [0x70cbf800,0xf0cff800)
allocated by thread T0 here:
    #0 0xf72aed06 in malloc (/usr/lib/i386-linux-gnu/libasan.so.2+0x96d06)
    #1 0x941fcb7 in zend_mm_mem_malloc_alloc /ramdisk/php-56/Zend/zend_alloc.c:287

SUMMARY: AddressSanitizer: memcpy-param-overlap ??:0 __asan_memcpy
==20971==ABORTING


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=72146&edit=1


Thread (1 message)

  • git@php.net
  • Unknown Message
    • git@php.net
« previous php.bugs (#235045) next »