php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73017 memory corruption in wordwrap function
Submitted: 2016-09-05 07:32 UTC Modified: 2017-02-13 01:25 UTC
From: minhrau dot vc dot 365 at gmail dot com Assigned: stas (profile)
Status: Closed Package: Strings related
PHP Version: 5.6.25 OS: ALL
Private report: No CVE-ID: None
 [2016-09-05 07:32 UTC] minhrau dot vc dot 365 at gmail dot com
Description:
------------
integer overflow cause memory corruption in wordwrap function:

PHP_FUNCTION(wordwrap)
{
	const char *text, *breakchar = "\n";
	char *newtext;
	int textlen, breakcharlen = 1, newtextlen, chk;
	size_t alloced;
	long current = 0, laststart = 0, lastspace = 0;
	long linelength = 75;
	zend_bool docut = 0;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lsb", &text, &textlen, &linelength, &breakchar, &breakcharlen, &docut) == FAILURE) {
		return;
	}
....

		RETURN_STRINGL(newtext, textlen, 0);
	} else {
		/* Multiple character line break or forced cut */
		if (linelength > 0) {
			chk = (int)(textlen/linelength + 1);
			newtext = safe_emalloc(chk, breakcharlen, textlen + 1);
			alloced = textlen + chk * breakcharlen + 1;
		} else {
			chk = textlen;
			alloced = textlen * (breakcharlen + 1) + 1;
			newtext = safe_emalloc(textlen, (breakcharlen + 1), 1);
		}

		/* now keep track of the actual new text length */
		newtextlen = 0;

		laststart = lastspace = 0;
...
			else if (current - laststart >= linelength
					&& laststart < lastspace) {
				memcpy(newtext+newtextlen, text+laststart, lastspace-laststart);//newtextlen will be negative and cause memory access violation
				newtextlen += lastspace - laststart;
				memcpy(newtext+newtextlen, breakchar, breakcharlen);
				newtextlen += breakcharlen;
				laststart = lastspace = lastspace + 1;
				chk--;
			}
		}

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

ini_set('memory_limit', -1);

$text = "The quick brown fox jumped over the lazy dog.";
$str = str_repeat($text, 0xffffffff/(100*2*strlen($text)));

var_dump(strlen($str));

$str1 = wordwrap($str, 20, str_repeat("a", 0xff1));
?>

Expected result:
----------------
No Crash

Actual result:
--------------
Break at string.c:995 and make this command:

commands 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
p newtext+newtextlen
p text+laststart
p newtextlen
p laststart
p lastspace-laststart
c
end


Starting program: /home/minhrau/PHP-5.6.25/sapi/cli/php testwordwrap_negative.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
int(21474810)

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff0e0fe1a in __memcpy_avx_unaligned () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff0e0fe1a in __memcpy_avx_unaligned () from /usr/lib/libc.so.6
#1  0x00000000008636dc in zif_wordwrap (ht=3, return_value=0x7ffff7fa0d68, return_value_ptr=0x7ffff7f6b140, this_ptr=0x0, return_value_used=1) at /home/minhrau/PHP-5.6.25/ext/standard/string.c:995
#2  0x00000000009d7844 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7f6b2b8) at /home/minhrau/PHP-5.6.25/Zend/zend_vm_execute.h:558
#3  0x00000000009df474 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x7ffff7f6b2b8) at /home/minhrau/PHP-5.6.25/Zend/zend_vm_execute.h:2602
#4  0x00000000009d5d37 in execute_ex (execute_data=0x7ffff7f6b2b8) at /home/minhrau/PHP-5.6.25/Zend/zend_vm_execute.h:363
#5  0x00000000009d6723 in zend_execute (op_array=0x7ffff7f9f858) at /home/minhrau/PHP-5.6.25/Zend/zend_vm_execute.h:388
#6  0x0000000000991c23 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/minhrau/PHP-5.6.25/Zend/zend.c:1341
#7  0x0000000000902b7f in php_execute_script (primary_file=0x7fffffffe2a0) at /home/minhrau/PHP-5.6.25/main/main.c:2613
#8  0x0000000000ab4902 in do_cli (argc=2, argv=0x1390960) at /home/minhrau/PHP-5.6.25/sapi/cli/php_cli.c:994
#9  0x0000000000ab5950 in main (argc=2, argv=0x1390960) at /home/minhrau/PHP-5.6.25/sapi/cli/php_cli.c:1378


Breakpoint 1, zif_wordwrap (ht=3, return_value=0x7ffff7fa2330, return_value_ptr=0x7ffff7f6c100, this_ptr=0x0, return_value_used=1) at /home/minhrau/PHP-5.6.25/ext/standard/string.c:995
995					memcpy(newtext+newtextlen, text+laststart, lastspace-laststart);
$2620156 = 0x7fff68af1e35 ""
$2620157 = 0x7fffefb71e35 "dog.The quick brown fox jumped over the lazy dog.The quick brown fox jumped over the lazy dog.The quick brown fox jumped over the lazy dog.The quick brown fox jumped over the lazy dog.The quick brown "...
$2620158 = 2147483141
$2620159 = 9432581
$2620160 = 19

Breakpoint 1, zif_wordwrap (ht=3, return_value=0x7ffff7fa2330, return_value_ptr=0x7ffff7f6c100, this_ptr=0x0, return_value_used=1) at /home/minhrau/PHP-5.6.25/ext/standard/string.c:995
995					memcpy(newtext+newtextlen, text+laststart, lastspace-laststart);
$2620161 = 0x7ffe68af2e39 <error: Cannot access memory at address 0x7ffe68af2e39>
$2620162 = 0x7fffefb71e49 "fox jumped over the lazy dog.The quick brown fox jumped over the lazy dog.The quick brown fox jumped over the lazy dog.The quick brown fox jumped over the lazy dog.The quick brown fox jumped over the "...
$2620163 = -2147480055
$2620164 = 9432601
$2620165 = 19

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff11ff7f8 in __memmove_avx_unaligned_erms () from /usr/lib/libc.so.6
(gdb)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-09-06 01:11 UTC] stas@php.net
-Assigned To: +Assigned To: stas
 [2016-09-06 01:11 UTC] stas@php.net
The fix is in security repo as fd42d3cab21295196e0b7c9df3ce85567c7bdad3 and in https://gist.github.com/fae8c27b6252cef6bfc33f7fddd03b6b
 [2016-09-13 04:12 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-09-13 04:12 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2016-10-03 07:33 UTC] minhrau dot vc dot 365 at gmail dot com
-Status: Closed +Status: Assigned
 [2016-10-03 07:33 UTC] minhrau dot vc dot 365 at gmail dot com
Please check again this patch. The patch did not check anything related to crash point.
 [2016-10-03 07:34 UTC] minhrau dot vc dot 365 at gmail dot com
-Status: Assigned +Status: Open
 [2016-10-03 07:34 UTC] minhrau dot vc dot 365 at gmail dot com
open this again
 [2016-10-03 23:53 UTC] stas@php.net
Looks like there are more issues there, I'll take a look.
 [2016-10-04 01:07 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=631173aa5c716f6d4a7bf1f6b7295482a46823bc
Log: Really fix bug #73017
 [2016-10-04 01:07 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-10-04 01:39 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=631173aa5c716f6d4a7bf1f6b7295482a46823bc
Log: Really fix bug #73017
 [2016-10-13 00:16 UTC] tyrael@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=28ed09929c8b0d76f1c0c3ecc82d4356231d556c
Log: Really fix bug #73017
 [2016-10-17 10:07 UTC] bwoebi@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=631173aa5c716f6d4a7bf1f6b7295482a46823bc
Log: Really fix bug #73017
 [2017-02-13 01:25 UTC] stas@php.net
-Type: Security +Type: Bug
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC