Bug #73505 [Opn->Csd]: string length overflow in mbfl_memory_device_output function
| From: | nikic@php.net | Date: | Sun, 23 Jul 2017 10:12:47 +0000 |
| Subject: | Bug #73505 [Opn->Csd]: string length overflow in mbfl_memory_device_output function | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-210224@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=73505&edit=1
ID: 73505
Updated by: nikic@php.net
Reported by: nguyenluan dot vnn at gmail dot com
Summary: string length overflow in mbfl_memory_device_output
function
-Status: Open
+Status: Closed
Type: Bug
Package: mbstring related
PHP Version: 5.6.28
-Assigned To:
+Assigned To: nikic
Block user comment: N
Private report: N
New Comment:
The specific issue here already seems to be resolved in PHP 7. The first duplicate is fixed in
master.
Previous Comments:
------------------------------------------------------------------------
[2016-11-26 22:56:22] stas@php.net
Related To: Bug #73268
------------------------------------------------------------------------
[2016-11-16 22:02:47] stas@php.net
Related To: Bug #73534
------------------------------------------------------------------------
[2016-11-12 12:34:31] nguyenluan dot vnn at gmail dot com
Description:
------------
This bug is related to Bug #73082.
The fix https://gist.github.com/anonymous/5677c59cc852e4935cad3571a0daf761,
although can prevent produce string with size larger than 2Gb but does NOT totally resolve this bug.
PHP 5 still crashes because the index value "device->pos" in function
mbfl_memory_device_output is larger than 2Gb.
int
mbfl_memory_device_output(int c, void *data)
{
mbfl_memory_device *device = (mbfl_memory_device *)data;
if (device->pos >= device->length) {
/* reallocate buffer */
int newlen;
unsigned char *tmp;
newlen = device->length + device->allocsz;
tmp = (unsigned char *)mbfl_realloc((void *)device->buffer, newlen*sizeof(unsigned char));
if (tmp == NULL) {
return -1;
}
device->length = newlen;
device->buffer = tmp;
}
device->buffer[device->pos++] = (unsigned char)c; // (1) crash here
return c;
}
Test script:
---------------
<?php
ini_set('memory_limit', -1);
$str = str_repeat("a", 0xffffffff/9); //a -> a output_len = input_len*5 ->
overflow integer
var_dump(strlen($str));
$str1 = mb_encode_numericentity ($str, array (0x0, 0xffff, 0, 0xffff), 'UTF-8');
?>
Expected result:
----------------
No crash.
Actual result:
--------------
gdb-peda$ r ../test/string/test.php
Starting program: /home/user/Desktop/php-5.6.28/sapi/cli/php ../test/string/test.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
int(477218588)
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x7ffe6b3e6070
RBX: 0xae8b93 (<execute_ex>: push rbp)
RCX: 0x80000001
RDX: 0x37 ('7')
RSI: 0x7ffeeb3e6070
("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...)
RDI: 0x37 ('7')
RBP: 0x7fffffffa4d0 --> 0x7fffffffa4f0 --> 0x7fffffffa540 --> 0x7fffffffa570 -->
0x7fffffffa610 --> 0x7fffffffa740 (--> ...)
RSP: 0x7fffffffa4a0 --> 0x7fffffffa5c0 --> 0x7ffeeb3e6070
("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...)
RIP: 0x78f6ba (<mbfl_memory_device_output+162>: mov BYTE PTR [rax],dl)
R8 : 0x280
R9 : 0x0
R10: 0x1
R11: 0x7ffff3603730 --> 0xfffda400fffda12f
R12: 0x444220 (<_start>: xor ebp,ebp)
R13: 0x7fffffffe1a0 --> 0x2
R14: 0x0
R15: 0x0
EFLAGS: 0x10203 (CARRY parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x78f6b2 <mbfl_memory_device_output+154>: cdqe
0x78f6b4 <mbfl_memory_device_output+156>: add rax,rsi
0x78f6b7 <mbfl_memory_device_output+159>: mov edx,DWORD PTR [rbp-0x24]
=> 0x78f6ba <mbfl_memory_device_output+162>: mov BYTE PTR [rax],dl
0x78f6bc <mbfl_memory_device_output+164>: mov eax,DWORD PTR [rbp-0x24]
0x78f6bf <mbfl_memory_device_output+167>: leave
0x78f6c0 <mbfl_memory_device_output+168>: ret
0x78f6c1 <mbfl_memory_device_output2>: push rbp
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffa4a0 --> 0x7fffffffa5c0 --> 0x7ffeeb3e6070
("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...)
0008| 0x7fffffffa4a8 --> 0x37f7fba377
0016| 0x7fffffffa4b0 --> 0x3748 ('H7')
0024| 0x7fffffffa4b8 --> 0x800008dc00000000
0032| 0x7fffffffa4c0 --> 0x7fffffffa5c0 --> 0x7ffeeb3e6070
("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...)
0040| 0x7fffffffa4c8 --> 0x7ffeeb3e6070
("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...)
0048| 0x7fffffffa4d0 --> 0x7fffffffa4f0 --> 0x7fffffffa540 --> 0x7fffffffa570 -->
0x7fffffffa610 --> 0x7fffffffa740 (--> ...)
0056| 0x7fffffffa4d8 --> 0x786713 (<mbfl_filt_conv_wchar_utf8+70>: test eax,eax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x000000000078f6ba in mbfl_memory_device_output (c=0x37, data=0x7fffffffa5c0)
at /home/user/Desktop/php-5.6.28/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c:157
157 device->buffer[device->pos++] = (unsigned char)c;
gdb-peda$ bt
#0 0x000000000078f6ba in mbfl_memory_device_output (c=0x37,
data=0x7fffffffa5c0)
at /home/user/Desktop/php-5.6.28/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c:157
#1 0x0000000000786713 in mbfl_filt_conv_wchar_utf8 (c=0x37,
filter=0x7ffff7fba738)
at /home/user/Desktop/php-5.6.28/ext/mbstring/libmbfl/filters/mbfilter_utf8.c:219
#2 0x000000000078d14e in collector_encode_htmlnumericentity (c=0x61,
data=0x7fffffffa5e0)
at /home/user/Desktop/php-5.6.28/ext/mbstring/libmbfl/mbfl/mbfilter.c:2709
#3 0x0000000000786388 in mbfl_filt_conv_utf8_wchar (c=0x61,
filter=0x7ffff7fba800)
at /home/user/Desktop/php-5.6.28/ext/mbstring/libmbfl/filters/mbfilter_utf8.c:118
#4 0x000000000078e0f4 in mbfl_html_numeric_entity (string=0x7fffffffa700,
result=0x7fffffffa720, convmap=0x7ffff7fb9bb8, mapsize=0x1, type=0x0)
at /home/user/Desktop/php-5.6.28/ext/mbstring/libmbfl/mbfl/mbfilter.c:3092
#5 0x000000000079a629 in php_mb_numericentity_exec (ht=0x3,
return_value=0x7ffff7fba6c0, return_value_ptr=0x7ffff7f80218,
this_ptr=0x0, return_value_used=0x1, type=0x0)
at /home/user/Desktop/php-5.6.28/ext/mbstring/mbstring.c:3842
#6 0x000000000079a79f in zif_mb_encode_numericentity (ht=0x3,
return_value=0x7ffff7fba6c0, return_value_ptr=0x7ffff7f80218,
this_ptr=0x0, return_value_used=0x1)
at /home/user/Desktop/php-5.6.28/ext/mbstring/mbstring.c:3856
#7 0x0000000000ae958b in zend_do_fcall_common_helper_SPEC (
execute_data=0x7ffff7f80310)
at /home/user/Desktop/php-5.6.28/Zend/zend_vm_execute.h:558
#8 0x0000000000aef0b6 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (
execute_data=0x7ffff7f80310)
at /home/user/Desktop/php-5.6.28/Zend/zend_vm_execute.h:2602
#9 0x0000000000ae8bf3 in execute_ex (execute_data=0x7ffff7f80310)
at /home/user/Desktop/php-5.6.28/Zend/zend_vm_execute.h:363
#10 0x0000000000ae8c7a in zend_execute (op_array=0x7ffff7fb84e0)
at /home/user/Desktop/php-5.6.28/Zend/zend_vm_execute.h:388
#11 0x0000000000aa162a in zend_execute_scripts (type=0x8, retval=0x0,
file_count=0x3) at /home/user/Desktop/php-5.6.28/Zend/zend.c:1341
#12 0x0000000000a0264f in php_execute_script (primary_file=0x7fffffffcd70)
at /home/user/Desktop/php-5.6.28/main/main.c:2613
#13 0x0000000000b5e442 in do_cli (argc=0x2, argv=0x1462630)
at /home/user/Desktop/php-5.6.28/sapi/cli/php_cli.c:998
#14 0x0000000000b5f7a5 in main (argc=0x2, argv=0x1462630)
at /home/user/Desktop/php-5.6.28/sapi/cli/php_cli.c:1382
#15 0x00007ffff348f830 in __libc_start_main (main=0xb5ef88 <main>, argc=0x2,
argv=0x7fffffffe1a8, init=<optimized out>, fini=<optimized out>,
rtld_fini=<optimized out>, stack_end=0x7fffffffe198)
at ../csu/libc-start.c:291
#16 0x0000000000444249 in _start ()
gdb-peda$ p device->pos
$1 = 0x80000001 // value larger than 2Gb
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=73505&edit=1