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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: nguyenluan dot vnn at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 14:01:32 2024 UTC