Bug #73648 [Opn->Csd]: Heap buffer overflow in substr

From: Date: Mon, 16 Jan 2017 20:14:31 +0000
Subject: Bug #73648 [Opn->Csd]: Heap buffer overflow in substr
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-206693@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=73648&edit=1 ID: 73648 Updated by: stas@php.net Reported by: fernando at null-life dot com Summary: Heap buffer overflow in substr -Status: Open +Status: Closed Type: Bug Package: Strings related Operating System: Linux 32 bits PHP Version: 7.0.14 Block user comment: N Private report: N New Comment: 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 Previous Comments: ------------------------------------------------------------------------ [2016-12-04 03:28:14] 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 ... ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=73648&edit=1

« previous php.bugs (#206693) next »