Commit message: Fix CVE-2019-13224: don't allow different encodings for onig_new_deluxe()
CVE: CVE-2019-13224
CWE: CWE-416
Vulnerability description: A use-after-free in onig_new_deluxe() in regext.c in Oniguruma 6.9.2 allows attackers to potentially cause information disclosure, denial of service, or possibly code execution by providing a crafted regular expression. The attacker provides a pair of a regex pattern and a string, with a multi-byte encoding that gets handled by onig_new_deluxe(). Oniguruma issues often affect Ruby, as well as common optional libraries for PHP and Rust.

Project: oniguruma
File: regext.c

conv_encoding(OnigEncoding from, OnigEncoding to, const UChar* s, const UChar* end,
              UChar** conv, UChar** conv_end)
{
  int len = (int )(end - s);

  if (to == ONIG_ENCODING_UTF16_BE) {
    if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) {
      *conv = (UChar* )xmalloc(len * 2);
      CHECK_NULL_RETURN_MEMERR(*conv);
      *conv_end = *conv + (len * 2);
      conv_ext0be(s, end, *conv);
      return 0;
    }
    else if (from == ONIG_ENCODING_UTF16_LE) {
    swap16:
      *conv = (UChar* )xmalloc(len);
      CHECK_NULL_RETURN_MEMERR(*conv);
      *conv_end = *conv + len;
      conv_swap2bytes(s, end, *conv);
      return 0;
    }
  }
  else if (to == ONIG_ENCODING_UTF16_LE) {
    if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) {
      *conv = (UChar* )xmalloc(len * 2);
      CHECK_NULL_RETURN_MEMERR(*conv);
      *conv_end = *conv + (len * 2);
      conv_ext0le(s, end, *conv);
      return 0;
    }
    else if (from == ONIG_ENCODING_UTF16_BE) {
      goto swap16;
    }
  }
  if (to == ONIG_ENCODING_UTF32_BE) {
    if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) {
      *conv = (UChar* )xmalloc(len * 4);
      CHECK_NULL_RETURN_MEMERR(*conv);
      *conv_end = *conv + (len * 4);
      conv_ext0be32(s, end, *conv);
      return 0;
    }
    else if (from == ONIG_ENCODING_UTF32_LE) {
    swap32:
      *conv = (UChar* )xmalloc(len);
      CHECK_NULL_RETURN_MEMERR(*conv);
      *conv_end = *conv + len;
      conv_swap4bytes(s, end, *conv);
      return 0;
    }
  }
  else if (to == ONIG_ENCODING_UTF32_LE) {
    if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) {
      *conv = (UChar* )xmalloc(len * 4);
      CHECK_NULL_RETURN_MEMERR(*conv);
      *conv_end = *conv + (len * 4);
      conv_ext0le32(s, end, *conv);
      return 0;
    }
    else if (from == ONIG_ENCODING_UTF32_BE) {
      goto swap32;
    }
  }
 
   return ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION;
 }

Project: oniguruma
File: regext.c

conv_ext0be(const UChar* s, const UChar* end, UChar* conv)
{
  while (s < end) {
    *conv++ = '\0';
    *conv++ = *s++;
  }
}

Project: oniguruma
File: regext.c

 conv_ext0be32(const UChar* s, const UChar* end, UChar* conv)
 {
  while (s < end) {
    *conv++ = '\0';
    *conv++ = '\0';
    *conv++ = '\0';
    *conv++ = *s++;
  }
}

Project: oniguruma
File: regext.c

conv_ext0le32(const UChar* s, const UChar* end, UChar* conv)
{
  while (s < end) {
    *conv++ = *s++;
    *conv++ = '\0';
    *conv++ = '\0';
    *conv++ = '\0';
  }
}

Project: oniguruma
File: regext.c

conv_swap2bytes(const UChar* s, const UChar* end, UChar* conv)
{
  while (s < end) {
    *conv++ = s[1];
    *conv++ = s[0];
    s += 2;
  }
}

Project: oniguruma
File: regext.c

conv_swap4bytes(const UChar* s, const UChar* end, UChar* conv)
{
  while (s < end) {
    *conv++ = s[3];
    *conv++ = s[2];
    *conv++ = s[1];
    *conv++ = s[0];
    s += 4;
  }
}