php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72405 mb_ereg_replace - mbc_to_code (oniguruma) - oob read access
Submitted: 2016-06-14 14:05 UTC Modified: 2021-08-22 04:22 UTC
From: shm@php.net Assigned: cmb (profile)
Status: No Feedback Package: mbstring related
PHP Version: 7.0Git-2016-06-14 (Git) OS: Linux
Private report: No CVE-ID: None
 [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

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-15 07:00 UTC] laruence@php.net
-Status: Open +Status: Feedback
 [2016-06-15 09:54 UTC] 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 15:49 UTC] laruence@php.net
hmm, this one seems really like a bug in oniguruma's bug..
 [2016-06-20 18:06 UTC] shm@php.net
Are you going to report it upstream?
 [2016-06-26 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 [2016-06-28 16:46 UTC] cmb@php.net
-Status: No Feedback +Status: Re-Opened
 [2016-06-28 16:46 UTC] cmb@php.net
Obivously, feedback had been provided, so re-opening.
 [2016-07-04 07:11 UTC] shm@php.net
@laurence - have you pushed this bug upstream?
 [2021-08-11 14:12 UTC] cmb@php.net
-Status: Re-Opened +Status: Feedback -Assigned To: +Assigned To: cmb
 [2021-08-11 14:12 UTC] cmb@php.net
What is the status here?  Has that been reported or even fixed
upstream?
 [2021-08-22 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC