Project: php-src (php/php-src), language: c++
Vulnerability instance: php.cve-2019-9023
Sanitizer: address

================= Bug Report (1/7) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=77370
## Description:
PHP Bug ID: 77370
Summary: Buffer overflow on mb regex functions - fetch_token
Status: Closed
PHP Version: 5.6.39
Assigned: stas (profile)
CVE-ID: 2019-9023

Description:
Description:
------------
Affects the $pattern of mb_ regex functions, such as mb_split, mb_ereg, and probably others given where my fix was.

In ext/mbstring/oniguruma/regparse.c, the function fetch_token takes a UChar **src, and a UChar *end. At completion of the method it sets *src to be where the pointer is currently (p). If there is an unfinished multibyte char at the end of the string then p can go beyond end. This causes flow on affects where src is then passed to onig_node_str_cat with *src which points past the end of the string buffer. This leads to a heap buffer overflow, which could cause memory corruption and/or leakage.

Could reproduce this on php 5.6.39, 7.0.33, and 7.1.25. I could not reproduce on 7.2.13, 7.3.0 or master due to the file being replaced.

A patch to fix is available at https://gist.github.com/hughdavenport/c5696e48ea3a83bfe12075f79b2b5abf

Test script:
---------------
php -r 'var_dump(mb_split("   \xfd",""));'

on php 5.6, weirdly it didn't crash with a plain string, but could get it to crash passing in a file.

$ xxd -g 1 mb_split_heap_crash-min5_6
00000000: fd                                               .

$ php -r 'var_dump(mb_ereg(file_get_contents($argv[1]),""));' mb_split_heap_crash-min5_6


Expected result:
----------------
no crash

Actual result:
--------------
$ ~/php-5.6.39/sapi/cli/php -r 'var_dump(mb_ereg(file_get_contents($argv[1]),""));' ../mb_split_heap_crash-min5_6
=================================================================
==16331==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000d7f2 at pc 0x0000004d67d1 bp 0x7ffcaa0ba840 sp 0x7ffcaa0b9ff0
READ of size 6 at 0x60200000d7f2 thread T0
    #0 0x4d67d0 in __asan_memcpy (/home/hugh/php-5.6.39/sapi/cli/php+0x4d67d0)
    #1 0x87dddb in onig_strcpy /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:223:5
    #2 0x87dddb in onig_node_str_cat /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1447
    #3 0x88e660 in node_new_str /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1506:7
    #4 0x88e660 in parse_exp /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5092
    #5 0x88c525 in parse_branch /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5441:7
    #6 0x889442 in parse_subexp /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5478:7
    #7 0x8802e5 in parse_regexp /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5522:7
    #8 0x8802e5 in onig_parse_make_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5549
    #9 0x805655 in onig_compile /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5300:7
    #10 0x82df69 in onig_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5545:7
    #11 0x9a7895 in php_mbregex_compile_pattern /home/hugh/php-5.6.39/ext/mbstring/php_mbregex.c:458:19
    #12 0x9a0809 in _php_mb_regex_ereg_exec /home/hugh/php-5.6.39/ext/mbstring/php_mbregex.c:728:7
    #13 0x11a27d8 in zend_do_fcall_common_helper_SPEC /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:558:5
    #14 0xffc73d in execute_ex /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:363:14
    #15 0xffe722 in zend_execute /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:388:2
    #16 0xebe557 in zend_eval_stringl /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1080:4
    #17 0xebfcd9 in zend_eval_stringl_ex /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1127:11
    #18 0xebfcd9 in zend_eval_string_ex /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1138
    #19 0x125a228 in do_cli /home/hugh/php-5.6.39/sapi/cli/php_cli.c:1038:8
    #20 0x12570a1 in main /home/hugh/php-5.6.39/sapi/cli/php_cli.c:1382:18
    #21 0x7f8fbd5ddb96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #22 0x436129 in _start (/home/hugh/php-5.6.39/sapi/cli/php+0x436129)

0x60200000d7f2 is located 0 bytes to the right of 2-byte region [0x60200000d7f0,0x60200000d7f2)
allocated by thread T0 here:
    #0 0x4ebba5 in realloc (/home/hugh/php-5.6.39/sapi/cli/php+0x4ebba5)
    #1 0xe10a82 in __zend_realloc /home/hugh/php-5.6.39/Zend/zend_alloc.h:114:6
    #2 0xb46252 in zif_file_get_contents /home/hugh/php-5.6.39/ext/standard/file.c:561:13
    #3 0x11a27d8 in zend_do_fcall_common_helper_SPEC /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:558:5

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/hugh/php-5.6.39/sapi/cli/php+0x4d67d0) in __asan_memcpy
Shadow bytes around the buggy address:
  0x0c047fff9aa0: fa fa fd fa fa fa 00 00 fa fa 00 05 fa fa fd fa
  0x0c047fff9ab0: fa fa 00 00 fa fa 00 05 fa fa 06 fa fa fa 07 fa
  0x0c047fff9ac0: fa fa 07 fa fa fa 04 fa fa fa fd fa fa fa fd fa
  0x0c047fff9ad0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fa
  0x0c047fff9ae0: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fa
=>0x0c047fff9af0: fa fa fd fa fa fa 00 00 fa fa fd fd fa fa[02]fa
  0x0c047fff9b00: fa fa 02 fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9b10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9b20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9b30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9b40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==16331==ABORTING



$ ~/php-7.0.33/sapi/cli/php -r 'var_dump(mb_ereg("   \xfd",""));'
=================================================================
==16351==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300001a3a0 at pc 0x0000004d8aa1 bp 0x7fffe4892ea0 sp 0x7fffe4892650
READ of size 6 at 0x60300001a3a0 thread T0
    #0 0x4d8aa0 in __asan_memcpy (/home/hugh/php-7.0.33/sapi/cli/php+0x4d8aa0)
    #1 0x85609b in onig_strcpy /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:223:5
    #2 0x85609b in onig_node_str_cat /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:1447
    #3 0x866ace in parse_exp /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5100:6
    #4 0x8647d5 in parse_branch /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5441:7
    #5 0x8616f2 in parse_subexp /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5478:7
    #6 0x8585a5 in parse_regexp /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5522:7
    #7 0x8585a5 in onig_parse_make_tree /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5549
    #8 0x7dd735 in onig_compile /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:5300:7
    #9 0x806029 in onig_new /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:5545:7
    #10 0x97f337 in php_mbregex_compile_pattern /home/hugh/php-7.0.33/ext/mbstring/php_mbregex.c:456:19
    #11 0x979a7e in _php_mb_regex_ereg_exec /home/hugh/php-7.0.33/ext/mbstring/php_mbregex.c:727:7
    #12 0x12588f5 in ZEND_DO_ICALL_SPEC_HANDLER /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:586:2
    #13 0x10da51d in execute_ex /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:417:7
    #14 0x10db3f7 in zend_execute /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:458:2
    #15 0xeefb24 in zend_eval_stringl /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1137:4
    #16 0xef062a in zend_eval_stringl_ex /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1178:11
    #17 0xef062a in zend_eval_string_ex /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1189
    #18 0x1319021 in do_cli /home/hugh/php-7.0.33/sapi/cli/php_cli.c:1008:8
    #19 0x1315f95 in main /home/hugh/php-7.0.33/sapi/cli/php_cli.c:1347:18
    #20 0x7f3c84dc2b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #21 0x4383f9 in _start (/home/hugh/php-7.0.33/sapi/cli/php+0x4383f9)

0x60300001a3a0 is located 0 bytes to the right of 32-byte region [0x60300001a380,0x60300001a3a0)
allocated by thread T0 here:
    #0 0x4eda50 in malloc (/home/hugh/php-7.0.33/sapi/cli/php+0x4eda50)
    #1 0xe2abcc in __zend_malloc /home/hugh/php-7.0.33/Zend/zend_alloc.c:2882:14
    #2 0xdd36f7 in lex_scan /home/hugh/php-7.0.33/Zend/zend_language_scanner.l:2054:5
    #3 0xe3af46 in zendlex /home/hugh/php-7.0.33/Zend/zend_compile.c:1587:11
    #4 0xd9fa05 in zendparse /home/hugh/php-7.0.33/Zend/zend_language_parser.c:4225:16
    #5 0xdb677e in compile_string /home/hugh/php-7.0.33/Zend/zend_language_scanner.l:760:8
    #6 0xeef95f in zend_eval_stringl /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1127:17
    #7 0xef062a in zend_eval_stringl_ex /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1178:11
    #8 0xef062a in zend_eval_string_ex /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1189

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/hugh/php-7.0.33/sapi/cli/php+0x4d8aa0) in __asan_memcpy
Shadow bytes around the buggy address:
  0x0c067fffb420: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00
  0x0c067fffb430: 00 00 fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
  0x0c067fffb440: 00 00 00 fa fa fa 00 00 00 00 fa fa 00 00 00 00
  0x0c067fffb450: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00
  0x0c067fffb460: 00 00 fa fa 00 00 00 00 fa fa fd fd fd fd fa fa
=>0x0c067fffb470: 00 00 00 00[fa]fa fd fd fd fd fa fa fa fa fa fa
  0x0c067fffb480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb490: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb4a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb4b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb4c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==16351==ABORTING

Comments:

[Comment 1] [2018-12-29 22:19 UTC] hugh at allthethings dot co dot nz
updating summary

[Comment 2] [2018-12-30 03:54 UTC] stas@php.net
Proposed fix in security repo as 0839641503bc381d64347081b4308dd7335a26b5 and in https://gist.github.com/smalyshev/4902bc13d34390d0068163d5d8fd64f7. Please verify.
Links: https://gist.github.com/smalyshev/4902bc13d34390d0068163d5d8fd64f7

[Comment 3] [2018-12-30 20:25 UTC] hugh at allthethings dot co dot nz
Verified on 7.1.25, 7.0.33, and 5.6.39.

Commit References:
0839641503bc381d64347081b4308dd7335a26b5

================= Bug Report (2/7) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=77371
## Description:
PHP Bug ID: 77371
Summary: heap buffer overflow in mb regex functions - compile_string_node
Status: Closed
PHP Version: 5.6.39
Assigned: stas (profile)
CVE-ID: 2019-9023

Description:
Description:
------------
After patching for #77370, I found another heap buffer overflow, based on incomplete multibyte strings in $pattern in mb regex functions such as mb_ereg, mb_split.

Narrowed the bug down to the compile_string_node function in ext/mbstring/oniguruma/regcomp.c. In the function, the length of a string is calculated, and is used in add_compile_string. If the string has an unfinished multibyte character at the end of the string, then the length will overflow the end of the buffer.

This could cause memory corruption and/or leakage.

Reproduced on 5.6, 7.0 and 7.1 (after patch for #77370 is applied, otherwise that case gets hit first). 7.2, 7.3 and master don't have this bug due to not having the file.

Patch is available at https://gist.github.com/hughdavenport/89849d35cc27c2242edcce4eb7c93520



Test script:
---------------
php -r 'var_dump(mb_ereg("()0\xfc00000\xfc00000\xfc00000\xfc",""));'

the patch from #77370 needs to be applied first to get to this point.

Expected result:
----------------
no crash

Actual result:
--------------
$ ~/php-5.6.39/sapi/cli/php -r 'var_dump(mb_ereg("()0\xfc00000\xfc00000\xfc00000\xfc",""));'
=================================================================
==4295==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000002c38 at pc 0x0000004d67d1 bp 0x7fff747ef860 sp 0x7fff747ef010
READ of size 24 at 0x606000002c38 thread T0
    #0 0x4d67d0 in __asan_memcpy (/home/hugh/php-5.6.39/sapi/cli/php+0x4d67d0)
    #1 0x847418 in add_bytes /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:284:3
    #2 0x847418 in add_compile_string /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:452
    #3 0x81a59a in compile_string_node /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:541:10
    #4 0x81a59a in compile_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:1627
    #5 0x8164f8 in compile_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:1590:11
    #6 0x8092a5 in onig_compile /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5390:7
    #7 0x82df69 in onig_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5545:7
    #8 0x9a7775 in php_mbregex_compile_pattern /home/hugh/php-5.6.39/ext/mbstring/php_mbregex.c:458:19
    #9 0x9a06e9 in _php_mb_regex_ereg_exec /home/hugh/php-5.6.39/ext/mbstring/php_mbregex.c:728:7
    #10 0x11a26b8 in zend_do_fcall_common_helper_SPEC /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:558:5
    #11 0xffc61d in execute_ex /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:363:14
    #12 0xffe602 in zend_execute /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:388:2
    #13 0xebe437 in zend_eval_stringl /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1080:4
    #14 0xebfbb9 in zend_eval_stringl_ex /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1127:11
    #15 0xebfbb9 in zend_eval_string_ex /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1138
    #16 0x125a108 in do_cli /home/hugh/php-5.6.39/sapi/cli/php_cli.c:1038:8
    #17 0x1256f81 in main /home/hugh/php-5.6.39/sapi/cli/php_cli.c:1382:18
    #18 0x7fe2c4e7fb96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #19 0x436129 in _start (/home/hugh/php-5.6.39/sapi/cli/php+0x436129)

0x606000002c38 is located 0 bytes to the right of 56-byte region [0x606000002c00,0x606000002c38)
allocated by thread T0 here:
    #0 0x4eb780 in malloc (/home/hugh/php-5.6.39/sapi/cli/php+0x4eb780)
    #1 0x87e8ff in node_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1120:18
    #2 0x87e8ff in node_new_str /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1498
    #3 0x87e8ff in onig_node_new_str /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1516
    #4 0x812709 in expand_case_fold_string /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3463:9
    #5 0x812709 in setup_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3686
    #6 0x8113e3 in setup_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3677:11
    #7 0x80ec76 in setup_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3666:6
    #8 0x805be8 in onig_compile /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5335:7
    #9 0x82df69 in onig_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5545:7

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/hugh/php-5.6.39/sapi/cli/php+0x4d67d0) in __asan_memcpy
Shadow bytes around the buggy address:
  0x0c0c7fff8530: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff8540: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c0c7fff8550: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8560: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff8570: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
=>0x0c0c7fff8580: 00 00 00 00 00 00 00[fa]fa fa fa fa 00 00 00 00
  0x0c0c7fff8590: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff85a0: fa fa fa fa 00 00 00 00 00 00 00 00 fa fa fa fa
  0x0c0c7fff85b0: 00 00 00 00 00 00 00 00 fa fa fa fa 00 00 00 00
  0x0c0c7fff85c0: 00 00 00 00 fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c0c7fff85d0: fa fa fa fa 00 00 00 00 00 00 00 00 fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==4295==ABORTING

Comments:

[Comment 1] [2018-12-30 04:07 UTC] stas@php.net
The fix is in security repo as d949cca738a67419c7d73f032ffe81ca6b77d803 and in https://gist.github.com/smalyshev/01688aa8e20317ee8c2ebc3cb4dd63b3

Please verify.
Links: https://gist.github.com/smalyshev/01688aa8e20317ee8c2ebc3cb4dd63b3

[Comment 2] [2018-12-30 20:41 UTC] hugh at allthethings dot co dot nz
Verified on 5.6, 7.0. Patch didn't apply cleanly to 7.1 (my bad!). Needs to test against sn->end instead of end in 7.1.25. That also fixes another bug I'm yet to file for 7.1, but still affects 5.6 and 7.0 so will hopefully write that up today

[Comment 3] [2018-12-30 21:09 UTC] hugh at allthethings dot co dot nz
Sorry, I had that file edited, but I found another instance where it could get fixed in compile_length_string_node. Should I just file another bug report for that along with a test case to keep them seperate?

Cheers,

Hugh

[Comment 4] [2018-12-30 22:39 UTC] hugh at allthethings dot co dot nz
#77381 is the new report for the one of the other enclen problems

Commit References:
d949cca738a67419c7d73f032ffe81ca6b77d803

================= Bug Report (3/7) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=77381
## Description:
PHP Bug ID: 77381
Summary: heap buffer overflow in multibyte match_at
Status: Closed
PHP Version: 5.6.39
Assigned: stas (profile)
CVE-ID: 2019-9023

Description:
Description:
------------
Caused by an incomplete multibyte char at end of $pattern in mb_split and mb_ereg. Leads to memory corruption and/or leakage.

Reproduced on 5.6.39, 7.0.33, and 7.1.25, not reproduced on 7.2, 7.3 and master.

Patch to fix available at https://gist.github.com/hughdavenport/3cb40fcf956085de44bf4443c25c58fe. Fixed by checking the length properly in compile_length_string_node.



Test script:
---------------
php -r 'var_dump(mb_ereg("000||0\xfa","0"));'


Expected result:
----------------
no crash

Actual result:
--------------
21:38 $ ~/src/php-src/sapi/cli/php -r 'var_dump(mb_ereg("000||0\xfa","0"));'
=================================================================
==32334==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300001c478 at pc 0x000000851e3e bp 0x7ffd64536450 sp 0x7ffd64536448
READ of size 1 at 0x60300001c478 thread T0
    #0 0x851e3d in match_at /home/hugh/src/php-src/ext/mbstring/oniguruma/regexec.c:1315:13
    #1 0x85424e in onig_search /home/hugh/src/php-src/ext/mbstring/oniguruma/regexec.c:3638:7
    #2 0x984949 in _php_mb_regex_ereg_exec /home/hugh/src/php-src/ext/mbstring/php_mbregex.c:753:6
    #3 0x12b1e72 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/hugh/src/php-src/Zend/zend_vm_execute.h:675:2
    #4 0x111aa0d in execute_ex /home/hugh/src/php-src/Zend/zend_vm_execute.h:432:7
    #5 0x111b9eb in zend_execute /home/hugh/src/php-src/Zend/zend_vm_execute.h:474:2
    #6 0xf1d950 in zend_eval_stringl /home/hugh/src/php-src/Zend/zend_execute_API.c:1120:4
    #7 0xf1e48a in zend_eval_stringl_ex /home/hugh/src/php-src/Zend/zend_execute_API.c:1161:11
    #8 0xf1e48a in zend_eval_string_ex /home/hugh/src/php-src/Zend/zend_execute_API.c:1172
    #9 0x13efbe8 in do_cli /home/hugh/src/php-src/sapi/cli/php_cli.c:1024:8
    #10 0x13ecba5 in main /home/hugh/src/php-src/sapi/cli/php_cli.c:1381:18
    #11 0x7f7d890f0b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #12 0x438cc9 in _start (/home/hugh/src/php-src/sapi/cli/php+0x438cc9)

0x60300001c478 is located 8 bytes to the left of 32-byte region [0x60300001c480,0x60300001c4a0)
allocated by thread T0 here:
    #0 0x4ee320 in malloc (/home/hugh/src/php-src/sapi/cli/php+0x4ee320)
    #1 0xe53fdc in __zend_malloc /home/hugh/src/php-src/Zend/zend_alloc.c:2838:14

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/hugh/src/php-src/ext/mbstring/oniguruma/regexec.c:1315:13 in match_at
Shadow bytes around the buggy address:
  0x0c067fffb830: 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00
  0x0c067fffb840: fa fa 00 00 00 00 fa fa 00 00 00 fa fa fa 00 00
  0x0c067fffb850: 00 fa fa fa 00 00 00 fa fa fa 00 00 00 00 fa fa
  0x0c067fffb860: 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00
  0x0c067fffb870: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa fd fd
=>0x0c067fffb880: fd fd fa fa 00 00 00 00 fa fa 00 00 00 04 fa[fa]
  0x0c067fffb890: 00 00 00 00 fa fa 00 00 00 00 fa fa fa fa fa fa
  0x0c067fffb8a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb8b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb8c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb8d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==32334==ABORTING

Comments:

[Comment 1] [2019-01-02 08:43 UTC] stas@php.net
I've made a common fix for four mbstring regex issues. It's in security repo as 6eb73547f231336d09e42d161ea6756b88832d46 and in https://gist.github.com/smalyshev/d5b79a07341ffdd77dc88860724bd2f5. Please verify.
Links: https://gist.github.com/smalyshev/d5b79a07341ffdd77dc88860724bd2f5

[Comment 2] [2019-01-02 21:16 UTC] hugh at allthethings dot co dot nz
Verified on 5.6, 7.0 and 7.1

[Comment 3] [2019-01-07 08:17 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.
Links: http://snaps.php.net/, http://windows.php.net/snapshots/

[Comment 4] [2019-01-07 08:18 UTC] stas@php.net
Related To: Bug #77382
Links: https://bugs.php.net/bug.php?id=77382

Commit References:
6eb73547f231336d09e42d161ea6756b88832d46

================= Bug Report (4/7) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=77382
## Description:
PHP Bug ID: 77382
Summary: heap buffer overflow due to incorrect length in expand_case_fold_string
Status: Closed
PHP Version: 5.6.39
Assigned: stas (profile)
CVE-ID: 2019-9023

Description:
Description:
------------
In expand_case_fold_string the len field is calculated off enclen, and is then used in onig_node_new_str which is passed to xmemcpy later down the line. This length may overshoot the string buffer if the last character is an unfinished multibyte character.

Patch available at https://gist.github.com/hughdavenport/aa428164c8f30d20c178ce0ab2907947

Test script:
---------------
php -r 'var_dump(mb_ereg("(?i)000000000000000000000\xf0",""));'

Expected result:
----------------
no crash

Actual result:
--------------
$ ~/php-5.6.39/sapi/cli/php -r 'var_dump(mb_split("(?i)000000000000000000000\xf0",""));'
=================================================================
==11478==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000001fd8 at pc 0x0000004d67d1 bp 0x7ffcde7b2e90 sp 0x7ffcde7b2640
READ of size 4 at 0x606000001fd8 thread T0
    #0 0x4d67d0 in __asan_memcpy (/home/hugh/php-5.6.39/sapi/cli/php+0x4d67d0)
    #1 0x87e12b in onig_strcpy /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:223:5
    #2 0x87e12b in onig_node_str_cat /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1456
    #3 0x87ed4e in node_new_str /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1515:7
    #4 0x87ed4e in onig_node_new_str /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1525
    #5 0x80e2a3 in expand_case_fold_string_alt /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3289:11
    #6 0x80e2a3 in expand_case_fold_string /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3431
    #7 0x80e2a3 in setup_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3687
    #8 0x8118d7 in setup_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:3810:8
    #9 0x805bd8 in onig_compile /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5336:7
    #10 0x82e2a9 in onig_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5546:7
    #11 0x9a6975 in php_mbregex_compile_pattern /home/hugh/php-5.6.39/ext/mbstring/php_mbregex.c:458:19
    #12 0x9a5c97 in zif_mb_split /home/hugh/php-5.6.39/ext/mbstring/php_mbregex.c:1076:12
    #13 0x11a18b8 in zend_do_fcall_common_helper_SPEC /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:558:5
    #14 0xffb81d in execute_ex /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:363:14
    #15 0xffd802 in zend_execute /home/hugh/php-5.6.39/Zend/zend_vm_execute.h:388:2
    #16 0xebd637 in zend_eval_stringl /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1080:4
    #17 0xebedb9 in zend_eval_stringl_ex /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1127:11
    #18 0xebedb9 in zend_eval_string_ex /home/hugh/php-5.6.39/Zend/zend_execute_API.c:1138
    #19 0x1259386 in do_cli /home/hugh/php-5.6.39/sapi/cli/php_cli.c:1040:31
    #20 0x1256181 in main /home/hugh/php-5.6.39/sapi/cli/php_cli.c:1386:18
    #21 0x7f66c1fb5b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #22 0x436129 in _start (/home/hugh/php-5.6.39/sapi/cli/php+0x436129)

0x606000001fd8 is located 0 bytes to the right of 56-byte region [0x606000001fa0,0x606000001fd8)
allocated by thread T0 here:
    #0 0x4eb780 in malloc (/home/hugh/php-5.6.39/sapi/cli/php+0x4eb780)
    #1 0x888fc3 in node_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1129:18
    #2 0x888fc3 in onig_node_new_alt /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:1266
    #3 0x888fc3 in parse_subexp /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5505
    #4 0x890c12 in parse_enclose /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:4551:11
    #5 0x890c12 in parse_exp /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5072
    #6 0x88c561 in parse_branch /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5460:11
    #7 0x888b22 in parse_subexp /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5487:7
    #8 0x880655 in parse_regexp /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5531:7
    #9 0x880655 in onig_parse_make_tree /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regparse.c:5558
    #10 0x805645 in onig_compile /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5301:7
    #11 0x82e2a9 in onig_new /home/hugh/php-5.6.39/ext/mbstring/oniguruma/regcomp.c:5546:7

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/hugh/php-5.6.39/sapi/cli/php+0x4d67d0) in __asan_memcpy
Shadow bytes around the buggy address:
  0x0c0c7fff83a0: 00 00 00 00 00 00 00 00 fa fa fa fa fd fd fd fd
  0x0c0c7fff83b0: fd fd fd fd fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff83c0: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c0c7fff83d0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff83e0: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
=>0x0c0c7fff83f0: fa fa fa fa 00 00 00 00 00 00 00[fa]fa fa fa fa
  0x0c0c7fff8400: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8410: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff8420: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c0c7fff8430: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8440: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==11478==ABORTING

Comments:

[Comment 1] [2019-01-02 08:43 UTC] stas@php.net
I've made a common fix for four mbstring regex issues. It's in security repo as 6eb73547f231336d09e42d161ea6756b88832d46 and in https://gist.github.com/smalyshev/d5b79a07341ffdd77dc88860724bd2f5. Please verify.
Links: https://gist.github.com/smalyshev/d5b79a07341ffdd77dc88860724bd2f5

[Comment 2] [2019-01-02 21:16 UTC] hugh at allthethings dot co dot nz
Verified on 5.6, 7.0 and 7.1

[Comment 3] [2019-01-07 08:18 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.

See bug #77381
Links: http://snaps.php.net/, http://windows.php.net/snapshots/, https://bugs.php.net/bug.php?id=77381

Commit References:
6eb73547f231336d09e42d161ea6756b88832d46

================= Bug Report (5/7) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=77385
## Description:
PHP Bug ID: 77385
Summary: buffer overflow in fetch_token
Status: Closed
PHP Version: 5.6.39
Assigned: stas (profile)
CVE-ID: 2019-9023

Description:
Description:
------------
Similar to #77370, using enclen on an incomplete multibyte character will return a pointer after the end of the buffer. This will cause memory corruption and/or leakage.

Patch available at https://gist.github.com/hughdavenport/09b48d4b20a28bcd7afaa530e2ec6731

Reproduced on 5.6.39, 7.0.33, 7.1.25, but not on 7.2, 7.3 and master.

Test script:
---------------
php -r 'var_dump(mb_ereg("0000\\"."\xf5","0"));'


Expected result:
----------------
no crash

Actual result:
--------------
$ ~/php-7.0.33/sapi/cli/php -r 'var_dump(mb_ereg("0000\\"."\xf5","0"));'
=================================================================
==27833==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300001a430 at pc 0x0000004d8aa1 bp 0x7ffe531d6220 sp 0x7ffe531d59d0
READ of size 4 at 0x60300001a430 thread T0
    #0 0x4d8aa0 in __asan_memcpy (/home/hugh/php-7.0.33/sapi/cli/php+0x4d8aa0)
    #1 0x85644b in onig_strcpy /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:223:5
    #2 0x85644b in onig_node_str_cat /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:1456
    #3 0x8667eb in parse_exp /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5109:6
    #4 0x864525 in parse_branch /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5450:7
    #5 0x860e42 in parse_subexp /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5487:7
    #6 0x858975 in parse_regexp /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5531:7
    #7 0x858975 in onig_parse_make_tree /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:5558
    #8 0x7dd735 in onig_compile /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:5302:7
    #9 0x806389 in onig_new /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:5547:7
    #10 0x97e487 in php_mbregex_compile_pattern /home/hugh/php-7.0.33/ext/mbstring/php_mbregex.c:456:19
    #11 0x978bce in _php_mb_regex_ereg_exec /home/hugh/php-7.0.33/ext/mbstring/php_mbregex.c:727:7
    #12 0x1257a45 in ZEND_DO_ICALL_SPEC_HANDLER /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:586:2
    #13 0x10d966d in execute_ex /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:417:7
    #14 0x10da547 in zend_execute /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:458:2
    #15 0xeeec74 in zend_eval_stringl /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1137:4
    #16 0xeef77a in zend_eval_stringl_ex /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1178:11
    #17 0xeef77a in zend_eval_string_ex /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1189
    #18 0x13181f6 in do_cli /home/hugh/php-7.0.33/sapi/cli/php_cli.c:1010:21
    #19 0x13150e5 in main /home/hugh/php-7.0.33/sapi/cli/php_cli.c:1350:18
    #20 0x7f239ba07b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #21 0x4383f9 in _start (/home/hugh/php-7.0.33/sapi/cli/php+0x4383f9)

0x60300001a430 is located 0 bytes to the right of 32-byte region [0x60300001a410,0x60300001a430)
allocated by thread T0 here:
    #0 0x4eda50 in malloc (/home/hugh/php-7.0.33/sapi/cli/php+0x4eda50)
    #1 0xe29d1c in __zend_malloc /home/hugh/php-7.0.33/Zend/zend_alloc.c:2882:14
    #2 0xeabfb5 in zend_try_ct_eval_binary_op /home/hugh/php-7.0.33/Zend/zend_compile.c:5881:2
    #3 0xeabfb5 in zend_compile_binary_op /home/hugh/php-7.0.33/Zend/zend_compile.c:5992
    #4 0xe411a6 in zend_compile_expr /home/hugh/php-7.0.33/Zend/zend_compile.c:7232:4
    #5 0xe59afd in zend_compile_args /home/hugh/php-7.0.33/Zend/zend_compile.c:2785:4
    #6 0xe5bcb0 in zend_compile_call_common /home/hugh/php-7.0.33/Zend/zend_compile.c:2873:14

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/hugh/php-7.0.33/sapi/cli/php+0x4d8aa0) in __asan_memcpy
Shadow bytes around the buggy address:
  0x0c067fffb430: 00 00 fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
  0x0c067fffb440: 00 00 00 fa fa fa 00 00 00 00 fa fa 00 00 00 00
  0x0c067fffb450: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00
  0x0c067fffb460: 00 00 fa fa 00 00 00 00 fa fa fd fd fd fd fa fa
  0x0c067fffb470: fd fd fd fd fa fa fd fd fd fd fa fa 00 00 00 00
=>0x0c067fffb480: fa fa 00 00 00 00[fa]fa fa fa fa fa fa fa fa fa
  0x0c067fffb490: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb4a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb4b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb4c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffb4d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==27833==ABORTING

Comments:

[Comment 1] [2019-01-02 08:44 UTC] stas@php.net
I've made a common fix for four mbstring regex issues. It's in security repo as 6eb73547f231336d09e42d161ea6756b88832d46 and in https://gist.github.com/smalyshev/d5b79a07341ffdd77dc88860724bd2f5. Please verify.
Links: https://gist.github.com/smalyshev/d5b79a07341ffdd77dc88860724bd2f5

[Comment 2] [2019-01-02 21:14 UTC] hugh at allthethings dot co dot nz
Verified on 5.6, 7.0 and 7.1

[Comment 3] [2019-01-07 08:18 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.
Links: http://snaps.php.net/, http://windows.php.net/snapshots/

Commit References:
6eb73547f231336d09e42d161ea6756b88832d46

================= Bug Report (6/7) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=77394
## Description:
PHP Bug ID: 77394
Summary: Buffer overflow in multibyte case folding - unicode
Status: Closed
PHP Version: 5.6.39
Assigned: stas (profile)
CVE-ID: 2019-9023

Description:
Description:
------------
When using mb regex functions such as mb_ereg and mb_split, with a pattern containing (?i) and a string ending with an incomplete multibyte character, then the case folding function will go past the end of the buffer. This can result in memory corruption and/or leakage.

Reproduced in 5.6.39, 7.0.33, and 7.1.25. Not an issue in 7.2, 7.3 and master.

Patch available at https://gist.github.com/hughdavenport/7f7b78c08aea058eaa955510d1548f12

Test script:
---------------
php -r 'var_dump(mb_ereg("(?i)FFF00000000000000000\xfd",""));'

Expected result:
----------------
no crash

Actual result:
--------------
$ ../php-7.0.33/sapi/cli/php -r 'var_dump(mb_ereg("(?i)FFF00000000000000000\xfd",""));'
=================================================================
==13642==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000003ad8 at pc 0x0000008914cc bp 0x7ffd807c7430 sp 0x7ffd807c7428
READ of size 1 at 0x606000003ad8 thread T0
    #0 0x8914cb in onigenc_unicode_mbc_case_fold /home/hugh/php-7.0.33/ext/mbstring/oniguruma/enc/unicode.c:11026:15
    #1 0x896600 in mbc_case_fold /home/hugh/php-7.0.33/ext/mbstring/oniguruma/enc/utf8.c:219:12
    #2 0x80bbfb in update_string_node_case_fold /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:3208:11
    #3 0x80bbfb in expand_case_fold_make_rem_string /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:3242
    #4 0x7ea7d9 in expand_case_fold_string /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:3465:9
    #5 0x7ea7d9 in setup_tree /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:3688
    #6 0x7e99c7 in setup_tree /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:3811:8
    #7 0x7ddcc8 in onig_compile /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:5337:7
    #8 0x806389 in onig_new /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:5547:7
    #9 0x97e487 in php_mbregex_compile_pattern /home/hugh/php-7.0.33/ext/mbstring/php_mbregex.c:456:19
    #10 0x978bce in _php_mb_regex_ereg_exec /home/hugh/php-7.0.33/ext/mbstring/php_mbregex.c:727:7
    #11 0x1257a45 in ZEND_DO_ICALL_SPEC_HANDLER /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:586:2
    #12 0x10d966d in execute_ex /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:417:7
    #13 0x10da547 in zend_execute /home/hugh/php-7.0.33/Zend/zend_vm_execute.h:458:2
    #14 0xeeec74 in zend_eval_stringl /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1137:4
    #15 0xeef77a in zend_eval_stringl_ex /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1178:11
    #16 0xeef77a in zend_eval_string_ex /home/hugh/php-7.0.33/Zend/zend_execute_API.c:1189
    #17 0x13181f6 in do_cli /home/hugh/php-7.0.33/sapi/cli/php_cli.c:1010:21
    #18 0x13150e5 in main /home/hugh/php-7.0.33/sapi/cli/php_cli.c:1350:18
    #19 0x7fb7612c5b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #20 0x4383f9 in _start (/home/hugh/php-7.0.33/sapi/cli/php+0x4383f9)

0x606000003ad8 is located 0 bytes to the right of 56-byte region [0x606000003aa0,0x606000003ad8)
allocated by thread T0 here:
    #0 0x4eda50 in malloc (/home/hugh/php-7.0.33/sapi/cli/php+0x4eda50)
    #1 0x856f6f in node_new /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:1129:18
    #2 0x856f6f in node_new_str /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:1507
    #3 0x856f6f in onig_node_new_str /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regparse.c:1525
    #4 0x7e94b3 in setup_tree /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:3679:11
    #5 0x7e6d56 in setup_tree /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:3668:6
    #6 0x7ddcc8 in onig_compile /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:5337:7
    #7 0x806389 in onig_new /home/hugh/php-7.0.33/ext/mbstring/oniguruma/regcomp.c:5547:7

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/hugh/php-7.0.33/ext/mbstring/oniguruma/enc/unicode.c:11026:15 in onigenc_unicode_mbc_case_fold
Shadow bytes around the buggy address:
  0x0c0c7fff8700: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8710: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff8720: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c0c7fff8730: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8740: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
=>0x0c0c7fff8750: fa fa fa fa 00 00 00 00 00 00 00[fa]fa fa fa fa
  0x0c0c7fff8760: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8770: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
  0x0c0c7fff8780: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c0c7fff8790: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff87a0: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==13642==ABORTING

Comments:

[Comment 1] [2019-01-02 08:44 UTC] stas@php.net
I've made a common fix for four mbstring regex issues. It's in security repo as 6eb73547f231336d09e42d161ea6756b88832d46 and in https://gist.github.com/smalyshev/d5b79a07341ffdd77dc88860724bd2f5. Please verify.
Links: https://gist.github.com/smalyshev/d5b79a07341ffdd77dc88860724bd2f5

[Comment 2] [2019-01-02 21:10 UTC] hugh at allthethings dot co dot nz
Verified on 5.6, 7.0 and 7.1

[Comment 3] [2019-01-07 08:18 UTC] stas@php.net
The fix for this bug has been committed.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.
Links: http://snaps.php.net/, http://windows.php.net/snapshots/

Commit References:
6eb73547f231336d09e42d161ea6756b88832d46

================= Bug Report (7/7) ==================
## Source: PHP Bugs
## URL: https://bugs.php.net/bug.php?id=77418
## Description:
PHP Bug ID: 77418
Summary: Heap overflow in utf32be_mbc_to_code
Status: Closed
PHP Version: 5.6.39
Assigned: stas (profile)
CVE-ID: 2019-9023

Description:
Description:
------------
The function utf32be_mbc_to_code assumes a buffer that contains 4 more characters in it (for a valid UTF-32 character). However, when a unterminated multibyte is passed to the regex match then the buffer will overflow.

Reproduced on 5.6.39, 7.0.33, 7.1.25, 7.2.13, 7.3.0 and master.

Patch available at https://gist.github.com/hughdavenport/3db8c2b9f92765c84196b387c32faaea

Test script:
---------------
php -r 'mb_regex_encoding("UTF-32");var_dump(mb_split("\x00\x00\x00\x5c\x00\x00\x00B","000000000000000000000000000000"));'


Expected result:
----------------
no crash

Actual result:
--------------
$ ../src/php-src/sapi/cli/php -r 'mb_regex_encoding("UTF-32");var_dump(mb_split("\x00\x00\x00\x5c\x00\x00\x00B","000000000000000000000000000000"));'
=================================================================
==27697==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000061d8 at pc 0x000000a0980f bp 0x7fffae9f0f60 sp 0x7fffae9f0f58
READ of size 1 at 0x6060000061d8 thread T0
    #0 0xa0980e in utf32be_mbc_to_code /home/hugh/src/php-src/ext/mbstring/oniguruma/src/utf32_be.c:70:70
    #1 0x993369 in match_at /home/hugh/src/php-src/ext/mbstring/oniguruma/src/regexec.c:3067:15
    #2 0x99ea2d in onig_search_with_param /home/hugh/src/php-src/ext/mbstring/oniguruma/src/regexec.c:4855:7
    #3 0x99c8e6 in onig_search /home/hugh/src/php-src/ext/mbstring/oniguruma/src/regexec.c:4614:7
    #4 0xae1a3c in zif_mb_split /home/hugh/src/php-src/ext/mbstring/php_mbregex.c:1265:9
    #5 0x1480525 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/hugh/src/php-src/Zend/zend_vm_execute.h:694:2
    #6 0x1270cfd in execute_ex /home/hugh/src/php-src/Zend/zend_vm_execute.h:55012:7
    #7 0x12716d6 in zend_execute /home/hugh/src/php-src/Zend/zend_vm_execute.h:60595:2
    #8 0x1083690 in zend_eval_stringl /home/hugh/src/php-src/Zend/zend_execute_API.c:1063:4
    #9 0x1083f1a in zend_eval_stringl_ex /home/hugh/src/php-src/Zend/zend_execute_API.c:1104:11
    #10 0x1083f1a in zend_eval_string_ex /home/hugh/src/php-src/Zend/zend_execute_API.c:1115
    #11 0x15b2127 in do_cli /home/hugh/src/php-src/sapi/cli/php_cli.c:1023:8
    #12 0x15aef3e in main /home/hugh/src/php-src/sapi/cli/php_cli.c:1384:18
    #13 0x7f79623c4b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #14 0x43bfe9 in _start (/home/hugh/src/php-src/sapi/cli/php+0x43bfe9)

0x6060000061d8 is located 0 bytes to the right of 56-byte region [0x6060000061a0,0x6060000061d8)
allocated by thread T0 here:
    #0 0x4f1640 in malloc (/home/hugh/src/php-src/sapi/cli/php+0x4f1640)
    #1 0xfd4a7c in __zend_malloc /home/hugh/src/php-src/Zend/zend_alloc.c:2930:14
    #2 0xfdec4c in zval_make_interned_string /home/hugh/src/php-src/Zend/zend_compile.c:478:16
    #3 0xfdec4c in zend_insert_literal /home/hugh/src/php-src/Zend/zend_compile.c:490
    #4 0xfdec4c in zend_add_literal /home/hugh/src/php-src/Zend/zend_compile.c:511
    #5 0xfdec4c in zend_emit_op /home/hugh/src/php-src/Zend/zend_compile.c:1988

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/hugh/src/php-src/ext/mbstring/oniguruma/src/utf32_be.c:70:70 in utf32be_mbc_to_code
Shadow bytes around the buggy address:
  0x0c0c7fff8be0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8bf0: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c0c7fff8c00: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c0c7fff8c10: 00 00 00 00 00 00 00 fa fa fa fa fa fd fd fd fd
  0x0c0c7fff8c20: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa
=>0x0c0c7fff8c30: fa fa fa fa 00 00 00 00 00 00 00[fa]fa fa fa fa
  0x0c0c7fff8c40: fd fd fd fd fd fd fd fa fa fa fa fa 00 00 00 00
  0x0c0c7fff8c50: 00 00 00 fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8c60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8c70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0c7fff8c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==27697==ABORTING

Comments:

[Comment 1] [2019-01-07 01:37 UTC] stas@php.net
OnigCodePoint is unsigned long, so converting NULL to it is not right. But I think we could probably just return 0 there.

[Comment 2] [2019-01-07 01:42 UTC] hugh at allthethings dot co dot nz
Yeh wasn't too sure on that as wasn't clear what a good error code would be. I've got a crash on UTF16 as well, I'll do a patch with 0 instead of NULL for that one.

[Comment 3] [2019-01-07 01:44 UTC] stas@php.net
this should fix it: https://gist.github.com/smalyshev/2b4a3c7d838e81f45f813090fe4db5ad

I'll add tests a bit later for the full patch
Links: https://gist.github.com/smalyshev/2b4a3c7d838e81f45f813090fe4db5ad

[Comment 4] [2019-01-07 01:56 UTC] stas@php.net
Related To: Bug #77419
Links: https://bugs.php.net/bug.php?id=77419

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
./buildconf --force
./configure \
        --enable-option-checking=fatal \
        --disable-libxml \
        --disable-dom \
        --disable-simplexml \
        --disable-xml \
        --disable-xmlreader \
        --disable-xmlwriter \
        --without-pear \
        --enable-exif \
        --disable-phpdbg \
        --disable-cgi
make -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool bison re2c make ca-certificates curl xz-utils dpkg-dev file libc-dev pkg-config libcurl4-openssl-dev libedit-dev libsqlite3-dev libssl-dev zlib1g-dev
RUN git clone https://github.com/php/php-src php-src
RUN git -C php-src checkout 05fb10165081cb4fb55a9943b44cab62c627db7a
WORKDIR $SRC/php-src
COPY build.sh $SRC/

Additional files: