php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72146 Integer overflow on substr_replace
Submitted: 2016-05-03 19:06 UTC Modified: 2021-07-14 15:22 UTC
From: fernando at null-life dot com Assigned: cmb (profile)
Status: Closed Package: Strings related
PHP Version: 5.6.21 OS: Linux
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: fernando at null-life dot com
New email:
PHP Version: OS:

 

 [2016-05-03 19:06 UTC] 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

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-05-13 02:18 UTC] stas@php.net
-Type: Security +Type: Bug
 [2016-05-13 02:18 UTC] stas@php.net
Doesn't look like security issue. May be size_t/int confusion again.
 [2016-12-07 18:41 UTC] fernando at null-life dot com
This issue (or a similar one) also affects PHP 7.1, keeps popping up on my server.
 [2021-07-14 15:22 UTC] cmb@php.net
-Status: Open +Status: Verified -Package: *General Issues +Package: Strings related -Assigned To: +Assigned To: cmb
 [2021-07-14 15:22 UTC] 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
 [2021-07-15 10:58 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/php-src/commit/33f8dfb15a34893d8311683db69ea857e66b8c90
Log: Fix #72146: Integer overflow on substr_replace
 [2021-07-15 10:58 UTC] git@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Dec 03 17:01:29 2024 UTC