Bug #72405 [Fbk]: mb_ereg_replace - mbc_to_code (oniguruma) - oob read access
| From: | laruence@php.net | Date: | Wed, 15 Jun 2016 15:49:22 +0000 |
| Subject: | Bug #72405 [Fbk]: mb_ereg_replace - mbc_to_code (oniguruma) - oob read access | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-201658@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72405&edit=1
ID: 72405
Updated by: laruence@php.net
Reported by: shm@php.net
Summary: mb_ereg_replace - mbc_to_code (oniguruma) - oob read
access
Status: Feedback
Type: Bug
Package: mbstring related
Operating System: Linux
PHP Version: 7.0Git-2016-06-14 (Git)
Block user comment: N
Private report: N
New Comment:
hmm, this one seems really like a bug in oniguruma's bug..
Previous Comments:
------------------------------------------------------------------------
[2016-06-15 09:54:26] shm@php.net
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
------------------------------------------------------------------------
[2016-06-15 07:00:29] laruence@php.net
According to https://github.com/php/php-src/blob/master/ext/mbstring/oniguruma/enc/utf8.c#L291
the max bytes are 6
so...I made a attempt to fix it here: https://github.com/php/php-src/commit/999a3553d58c537b4919821855b2cc8fb62b0b2f
thanks
------------------------------------------------------------------------
[2016-06-14 14:05:04] 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
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=72405&edit=1