php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73505 string length overflow in mbfl_memory_device_output function
Submitted: 2016-11-12 12:34 UTC Modified: 2017-07-23 10:12 UTC
From: nguyenluan dot vnn at gmail dot com Assigned: nikic (profile)
Status: Closed Package: mbstring related
PHP Version: 5.6.28 OS:
Private report: No CVE-ID: None
 [2016-11-12 12:34 UTC] 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 -> &#97; 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 ("&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;"...)
RDI: 0x37 ('7')
RBP: 0x7fffffffa4d0 --> 0x7fffffffa4f0 --> 0x7fffffffa540 --> 0x7fffffffa570 --> 0x7fffffffa610 --> 0x7fffffffa740 (--> ...)
RSP: 0x7fffffffa4a0 --> 0x7fffffffa5c0 --> 0x7ffeeb3e6070 ("&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;"...)
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 ("&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;"...)
0008| 0x7fffffffa4a8 --> 0x37f7fba377 
0016| 0x7fffffffa4b0 --> 0x3748 ('H7')
0024| 0x7fffffffa4b8 --> 0x800008dc00000000 
0032| 0x7fffffffa4c0 --> 0x7fffffffa5c0 --> 0x7ffeeb3e6070 ("&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;"...)
0040| 0x7fffffffa4c8 --> 0x7ffeeb3e6070 ("&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;&#97;"...)
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


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-11-26 22:49 UTC] stas@php.net
-Type: Security +Type: Bug
 [2017-07-23 10:12 UTC] nikic@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: nikic
 [2017-07-23 10:12 UTC] nikic@php.net
The specific issue here already seems to be resolved in PHP 7. The first duplicate is fixed in master.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Mon Oct 18 18:03:40 2021 UTC