|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-06-14 14:05 UTC] shm@php.net
Description:
------------
mbc_to_code which is part of oniguruma library performs oob access if pattern is shorter than 6 characters. I'm not sure if it's PHP bug (due to misuse of oniugurma API or oniguruma internals bug, if so then please consider sending it upstream).
DEBUGGER SESSION:
Breakpoint 3, mbc_to_code (p=0x7fffffffa040 <incomplete sequence \374>, end=0x7fffffffa041 "") at /home/shm/src/php-src/ext/mbstring/oniguruma/enc/utf8.c:99
99 len = enclen(ONIG_ENCODING_UTF8, p);
gdb-peda$
at the beginning we pushed to function following pattern "0xfc00"
gdb-peda$ x/x p
0x7fffffffa040: 0x00000000000000fc
gdb-peda$ c
Program received signal SIGABRT, Aborted.
gdb-peda$
#7 0x0000000000a08355 in mbc_to_code (p=0x7fffffffa045 "", end=0x7fffffffa041 "") at /home/shm/src/php-src/ext/mbstring/oniguruma/enc/utf8.c:105
105 c = *p++;
gdb-peda$ print p
$35 = (const OnigUChar *) 0x7fffffffa045 ""
p is greater than end (which is unused in mbc_to_token). Pattern which is used in this function comes from _php_mb_regex_ereg_replace_exec Where pat_buf is declared as follows:
810 char pat_buf[4];
then gets initialized here:
857 /* FIXME: this code is not multibyte aware! */
858 convert_to_long_ex(arg_pattern_zval);
859 pat_buf[0] = (char)Z_LVAL_P(arg_pattern_zval);
860 pat_buf[1] = '\0';
861 pat_buf[2] = '\0';
862 pat_buf[3] = '\0';
863
864 arg_pattern = pat_buf;
865 arg_pattern_len = 1;
Note the FIXME comment. Then it's used here:
868 re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax);
which internally calls mbc_to_code
ASAN REPORT:
==20738==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff5c361494 at pc 0xa0b97d bp 0x7fff5c360790 sp 0x7fff5c360788
READ of size 1 at 0x7fff5c361494 thread T0
#0 0xa0b97c in mbc_to_code /home/shm/src/php-7.0.2/ext/mbstring/oniguruma/enc/utf8.c:105
#1 0x9f0420 in fetch_token /home/shm/src/php-7.0.2/ext/mbstring/oniguruma/regparse.c:3146
#2 0x9ff729 in parse_regexp /home/shm/src/php-7.0.2/ext/mbstring/oniguruma/regparse.c:5514
#3 0x9ffba6 in onig_parse_make_tree /home/shm/src/php-7.0.2/ext/mbstring/oniguruma/regparse.c:5543
#4 0x9c3b15 in onig_compile /home/shm/src/php-7.0.2/ext/mbstring/oniguruma/regcomp.c:5300
#5 0x9c4b8d in onig_new /home/shm/src/php-7.0.2/ext/mbstring/oniguruma/regcomp.c:5545
#6 0xaa051a in php_mbregex_compile_pattern /home/shm/src/php-7.0.2/ext/mbstring/php_mbregex.c:456
#7 0xaa26c8 in _php_mb_regex_ereg_replace_exec /home/shm/src/php-7.0.2/ext/mbstring/php_mbregex.c:868
#8 0xaa3a82 in zif_mb_ereg_replace /home/shm/src/php-7.0.2/ext/mbstring/php_mbregex.c:1029
#9 0x10eaac9 in ZEND_DO_ICALL_SPEC_HANDLER /home/shm/src/php-7.0.2/Zend/zend_vm_execute.h:586
#10 0x10e9b22 in execute_ex /home/shm/src/php-7.0.2/Zend/zend_vm_execute.h:414
#11 0x10e9da1 in zend_execute /home/shm/src/php-7.0.2/Zend/zend_vm_execute.h:458
#12 0xfc7b37 in zend_eval_stringl /home/shm/src/php-7.0.2/Zend/zend_execute_API.c:1129
#13 0xb82b53 in readline_shell_run /home/shm/src/php-7.0.2/ext/readline/readline_cli.c:669
#14 0x1223447 in do_cli /home/shm/src/php-7.0.2/sapi/cli/php_cli.c:972
#15 0x1225daa in main /home/shm/src/php-7.0.2/sapi/cli/php_cli.c:1345
#16 0x7fd94f301ec4 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
#17 0x42e208 (/home/shm/src/php-7.0.2/sapi/cli/php+0x42e208)
Address 0x7fff5c361494 is located in stack of thread T0 at offset 1156 in frame
#0 0xaa1e67 in _php_mb_regex_ereg_replace_exec /home/shm/src/php-7.0.2/ext/mbstring/php_mbregex.c:784
This frame has 18 object(s):
[32, 36) 'eval'
[96, 104) 'arg_pattern_zval'
[160, 168) 'replace'
[224, 232) 'replace_len'
[288, 296) 'string'
[352, 360) 'string_len'
[416, 424) 'syntax'
[480, 488) 'option_str'
[544, 552) 'option_str_len'
[608, 624) 'out_buf'
[672, 688) 'eval_buf'
[736, 752) 'args'
[800, 816) 'subpats'
[864, 880) 'retval'
[928, 968) 'arg_replace_fci_cache'
[1024, 1096) 'arg_replace_fci'
[1152, 1156) 'pat_buf' <== Memory access at offset 1156 overflows this variable
[1216, 1306) 'err_str'
Test script:
---------------
<?php
mb_ereg_replace(0xfc,$_,$_);
Expected result:
----------------
No oob access
Actual result:
--------------
Oob access in mbc_to_code
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 07:00:01 2025 UTC |
For provided case it works perfectly, but we've got another case if user provided string shorter than 6 chars, like this one: <?php mb_ereg_replace("\xfc",$_,$_); Function reads oob (but it's not using pat_buf). 105 c = *p++; gdb-peda$ print p $7 = (const OnigUChar *) 0x60060004ffdc "" gdb-peda$ bt #0 mbc_to_code (p=0x60060004ffdc "", end=0x60060004ffd9 "") at /home/shm/src/php-src/ext/mbstring/oniguruma/enc/utf8.c:105