Project

General

Profile

Bug #12423

Regexp: Heap Buffer Overflow in regparse.c : next_state_value()

Added by grajagandev (David Moore) about 3 years ago. Updated about 3 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.3.1p112 (2016-04-26 revision 54768) [i686-linux]
[ruby-core:75709]

Description

A crafted regular expression will cause a heap buffer overflow leading to invalid 4 byte reads/writes on 32-bit Ubuntu 14.04. The regular expression fails to close a character class and has an octal zero as the first character in the character class.

Despite the buffer overflow, ruby does not crash. This bug may have the same root cause as #12420.

grajagandev# cat load-re.rb 
File.open(ARGV[0]) do |f|  
  @re = Regexp.new("/" + File.read(f) + "/")
end  
grajagandev# xxd overflow-next_state_value
0000000: 5b5c 3630 3030 3030 3030 3030 3030 0a    [\600000000000.
grajagandev# ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [i686-linux]
grajagandev# uname -a
Linux x-Acer 3.19.0-25-generic #26~14.04.1-Ubuntu SMP Fri Jul 24 21:18:00 UTC 2015 i686 i686 i686 GNU/Linux
grajagandev# ruby load-re.rb overflow-next_state_value
=================================================================
==11873== ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb470cd88 at pc 0xb730f9fd bp 0xbfc4d458 sp 0xbfc4d44c
READ of size 4 at 0xb470cd88 thread T0
    #0 0xb730f9fc (/usr/local/bin/ruby+0x1cb9fc)
    #1 0xb73116c9 (/usr/local/bin/ruby+0x1cd6c9)
    #2 0xb731a6fb (/usr/local/bin/ruby+0x1d66fb)
    #3 0xb731b856 (/usr/local/bin/ruby+0x1d7856)
    #4 0xb731baee (/usr/local/bin/ruby+0x1d7aee)
    #5 0xb731bdd9 (/usr/local/bin/ruby+0x1d7dd9)
    #6 0xb731c376 (/usr/local/bin/ruby+0x1d8376)
    #7 0xb72ccf09 (/usr/local/bin/ruby+0x188f09)
    #8 0xb729a77f (/usr/local/bin/ruby+0x15677f)
    #9 0xb729a8b6 (/usr/local/bin/ruby+0x1568b6)
    #10 0xb72a586e (/usr/local/bin/ruby+0x16186e)
    #11 0xb72a5bc1 (/usr/local/bin/ruby+0x161bc1)
    #12 0xb72a943c (/usr/local/bin/ruby+0x16543c)
    #13 0xb7450da4 (/usr/local/bin/ruby+0x30cda4)
    #14 0xb74844a6 (/usr/local/bin/ruby+0x3404a6)
    #15 0xb74845fc (/usr/local/bin/ruby+0x3405fc)
    #16 0xb7484be3 (/usr/local/bin/ruby+0x340be3)
    #17 0xb7483fbd (/usr/local/bin/ruby+0x33ffbd)
    #18 0xb74860ed (/usr/local/bin/ruby+0x3420ed)
    #19 0xb748763d (/usr/local/bin/ruby+0x34363d)
    #20 0xb74884cd (/usr/local/bin/ruby+0x3444cd)
    #21 0xb718477e (/usr/local/bin/ruby+0x4077e)
    #22 0xb72549ed (/usr/local/bin/ruby+0x1109ed)
    #23 0xb7450da4 (/usr/local/bin/ruby+0x30cda4)
    #24 0xb745342d (/usr/local/bin/ruby+0x30f42d)
    #25 0xb745368d (/usr/local/bin/ruby+0x30f68d)
    #26 0xb7456088 (/usr/local/bin/ruby+0x312088)
    #27 0xb74574da (/usr/local/bin/ruby+0x3134da)
    #28 0xb74578b2 (/usr/local/bin/ruby+0x3138b2)
    #29 0xb7465a0b (/usr/local/bin/ruby+0x321a0b)
    #30 0xb749718c (/usr/local/bin/ruby+0x35318c)
    #31 0xb7492c08 (/usr/local/bin/ruby+0x34ec08)
    #32 0xb74935db (/usr/local/bin/ruby+0x34f5db)
    #33 0xb7493686 (/usr/local/bin/ruby+0x34f686)
    #34 0xb7493882 (/usr/local/bin/ruby+0x34f882)
    #35 0xb7488eae (/usr/local/bin/ruby+0x344eae)
    #36 0xb7488ecd (/usr/local/bin/ruby+0x344ecd)
    #37 0xb7488efc (/usr/local/bin/ruby+0x344efc)
    #38 0xb718289f (/usr/local/bin/ruby+0x3e89f)
    #39 0xb7203f64 (/usr/local/bin/ruby+0xbff64)
    #40 0xb7450da4 (/usr/local/bin/ruby+0x30cda4)
    #41 0xb745342d (/usr/local/bin/ruby+0x30f42d)
    #42 0xb745368d (/usr/local/bin/ruby+0x30f68d)
    #43 0xb7456088 (/usr/local/bin/ruby+0x312088)
    #44 0xb74574da (/usr/local/bin/ruby+0x3134da)
    #45 0xb74578b2 (/usr/local/bin/ruby+0x3138b2)
    #46 0xb746510f (/usr/local/bin/ruby+0x32110f)
    #47 0xb749718c (/usr/local/bin/ruby+0x35318c)
    #48 0xb74997a5 (/usr/local/bin/ruby+0x3557a5)
    #49 0xb717f669 (/usr/local/bin/ruby+0x3b669)
    #50 0xb717f8cd (/usr/local/bin/ruby+0x3b8cd)
    #51 0xb717f882 (/usr/local/bin/ruby+0x3b882)
    #52 0xb717a1a3 (/usr/local/bin/ruby+0x361a3)
    #53 0xb58f6a82 (/lib/i386-linux-gnu/libc-2.19.so+0x19a82)
    #54 0xb7179fd0 (/usr/local/bin/ruby+0x35fd0)
0xb470cd88 is located 8 bytes to the left of 44-byte region [0xb470cd90,0xb470cdbc)
allocated by thread T0 here:
    #0 0xb5b3a854 (/usr/lib/i386-linux-gnu/libasan.so.0.0.0+0x16854)
    #1 0xb72f61f2 (/usr/local/bin/ruby+0x1b21f2)
    #2 0xb72f7d84 (/usr/local/bin/ruby+0x1b3d84)
    #3 0xb731b245 (/usr/local/bin/ruby+0x1d7245)
    #4 0xb731b75d (/usr/local/bin/ruby+0x1d775d)
    #5 0xb731baee (/usr/local/bin/ruby+0x1d7aee)
    #6 0xb7315d4c (/usr/local/bin/ruby+0x1d1d4c)
    #7 0xb7318dc0 (/usr/local/bin/ruby+0x1d4dc0)
    #8 0xb731b856 (/usr/local/bin/ruby+0x1d7856)
    #9 0xb731baee (/usr/local/bin/ruby+0x1d7aee)
    #10 0xb731bdd9 (/usr/local/bin/ruby+0x1d7dd9)
    #11 0xb731c376 (/usr/local/bin/ruby+0x1d8376)
    #12 0xb72ccf09 (/usr/local/bin/ruby+0x188f09)
    #13 0xb729a77f (/usr/local/bin/ruby+0x15677f)
    #14 0xb729a8b6 (/usr/local/bin/ruby+0x1568b6)
    #15 0xb72a586e (/usr/local/bin/ruby+0x16186e)
    #16 0xb72a5bc1 (/usr/local/bin/ruby+0x161bc1)
    #17 0xb72a62cf (/usr/local/bin/ruby+0x1622cf)
    #18 0xb75afcb2 (/usr/local/bin/ruby+0x46bcb2)
    #19 0xb75afcef (/usr/local/bin/ruby+0x46bcef)
    #20 0xb757ff6a (/usr/local/bin/ruby+0x43bf6a)
    #21 0xb758a473 (/usr/local/bin/ruby+0x446473)
    #22 0xb74acc2c (/usr/local/bin/ruby+0x368c2c)
    #23 0xb758aa46 (/usr/local/bin/ruby+0x446a46)
    #24 0xb758b64c (/usr/local/bin/ruby+0x44764c)
    #25 0xb7326787 (/usr/local/bin/ruby+0x1e2787)
    #26 0xb718289f (/usr/local/bin/ruby+0x3e89f)
    #27 0xb7327029 (/usr/local/bin/ruby+0x1e3029)
    #28 0xb73270f2 (/usr/local/bin/ruby+0x1e30f2)
    #29 0xb7189871 (/usr/local/bin/ruby+0x45871)
Shadow bytes around the buggy address:
  0x368e1960: fa fa 00 00 00 00 00 fa fa fa fd fd fd fd fd fa
  0x368e1970: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 04
  0x368e1980: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
  0x368e1990: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
  0x368e19a0: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
=>0x368e19b0: fa[fa]00 00 00 00 00 04 fa fa 00 00 00 00 00 04
  0x368e19c0: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 04
  0x368e19d0: fa fa 00 00 00 00 00 04 fa fa 00 00 00 00 00 fa
  0x368e19e0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
  0x368e19f0: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
  0x368e1a00: fa fa fd fd fd fd fd fd fa fa 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
  Heap righ redzone:     fb
  Freed Heap region:     fd
  Stack left redzone:    f1
  Stack mid redzone:     f2
  Stack right redzone:   f3
  Stack partial redzone: f4
  Stack after return:    f5
  Stack use after scope: f8
  Global redzone:        f9
  Global init order:     f6
  Poisoned by user:      f7
  ASan internal:         fe
==11873== ABORTING
grajagandev#
grajagandev# valgrind --max-stackframe=90000000 ruby load-re.rb overflow-next_state_value
==23692== Memcheck, a memory error detector
==23692== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==23692== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==23692== Command: ruby load-re.rb overflow-next_state_value
==23692== 
==23692== Invalid read of size 4
==23692==    at 0x1C9588: next_state_val (regparse.c:4478)
==23692==    by 0x1CA0D7: parse_char_class (regparse.c:4725)
==23692==    by 0x1CD36D: parse_exp (regparse.c:6187)
==23692==    by 0x1CD8F5: parse_branch (regparse.c:6365)
==23692==    by 0x1CD9BD: parse_subexp (regparse.c:6395)
==23692==    by 0x1CDB5D: parse_regexp (regparse.c:6443)
==23692==    by 0x1CDC80: onig_parse_make_tree (regparse.c:6485)
==23692==    by 0x1B27C6: onig_compile (regcomp.c:5739)
==23692==    by 0x1A0C20: onig_new_with_source (re.c:849)
==23692==    by 0x1A0CA8: make_regexp (re.c:873)
==23692==    by 0x1A479D: rb_reg_initialize (re.c:2546)
==23692==    by 0x1A4905: rb_reg_initialize_str (re.c:2571)
==23692==  Address 0x4cb6180 is 12 bytes after a block of size 44 alloc'd
==23692==    at 0x482A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==23692==    by 0x1C14CD: node_new (regparse.c:1151)
==23692==    by 0x1C17D0: node_new_list (regparse.c:1291)
==23692==    by 0x1CD953: parse_branch (regparse.c:6377)
==23692==    by 0x1CD9BD: parse_subexp (regparse.c:6395)
==23692==    by 0x1CDB5D: parse_regexp (regparse.c:6443)
==23692==    by 0x1CDC80: onig_parse_make_tree (regparse.c:6485)
==23692==    by 0x1B27C6: onig_compile (regcomp.c:5739)
==23692==    by 0x1A0C20: onig_new_with_source (re.c:849)
==23692==    by 0x1A0CA8: make_regexp (re.c:873)
==23692==    by 0x1A479D: rb_reg_initialize (re.c:2546)
==23692==    by 0x1A4905: rb_reg_initialize_str (re.c:2571)
==23692== 
==23692== Invalid read of size 4
==23692==    at 0x1C95CB: next_state_val (regparse.c:4478)
==23692==    by 0x1CA0D7: parse_char_class (regparse.c:4725)
==23692==    by 0x1CD36D: parse_exp (regparse.c:6187)
==23692==    by 0x1CD8F5: parse_branch (regparse.c:6365)
==23692==    by 0x1CD9BD: parse_subexp (regparse.c:6395)
==23692==    by 0x1CDB5D: parse_regexp (regparse.c:6443)
==23692==    by 0x1CDC80: onig_parse_make_tree (regparse.c:6485)
==23692==    by 0x1B27C6: onig_compile (regcomp.c:5739)
==23692==    by 0x1A0C20: onig_new_with_source (re.c:849)
==23692==    by 0x1A0CA8: make_regexp (re.c:873)
==23692==    by 0x1A479D: rb_reg_initialize (re.c:2546)
==23692==    by 0x1A4905: rb_reg_initialize_str (re.c:2571)
==23692==  Address 0x4cb6180 is 12 bytes after a block of size 44 alloc'd
==23692==    at 0x482A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==23692==    by 0x1C14CD: node_new (regparse.c:1151)
==23692==    by 0x1C17D0: node_new_list (regparse.c:1291)
==23692==    by 0x1CD953: parse_branch (regparse.c:6377)
==23692==    by 0x1CD9BD: parse_subexp (regparse.c:6395)
==23692==    by 0x1CDB5D: parse_regexp (regparse.c:6443)
==23692==    by 0x1CDC80: onig_parse_make_tree (regparse.c:6485)
==23692==    by 0x1B27C6: onig_compile (regcomp.c:5739)
==23692==    by 0x1A0C20: onig_new_with_source (re.c:849)
==23692==    by 0x1A0CA8: make_regexp (re.c:873)
==23692==    by 0x1A479D: rb_reg_initialize (re.c:2546)
==23692==    by 0x1A4905: rb_reg_initialize_str (re.c:2571)
==23692== 
==23692== Invalid write of size 4
==23692==    at 0x1C95F5: next_state_val (regparse.c:4478)
==23692==    by 0x1CA0D7: parse_char_class (regparse.c:4725)
==23692==    by 0x1CD36D: parse_exp (regparse.c:6187)
==23692==    by 0x1CD8F5: parse_branch (regparse.c:6365)
==23692==    by 0x1CD9BD: parse_subexp (regparse.c:6395)
==23692==    by 0x1CDB5D: parse_regexp (regparse.c:6443)
==23692==    by 0x1CDC80: onig_parse_make_tree (regparse.c:6485)
==23692==    by 0x1B27C6: onig_compile (regcomp.c:5739)
==23692==    by 0x1A0C20: onig_new_with_source (re.c:849)
==23692==    by 0x1A0CA8: make_regexp (re.c:873)
==23692==    by 0x1A479D: rb_reg_initialize (re.c:2546)
==23692==    by 0x1A4905: rb_reg_initialize_str (re.c:2571)
==23692==  Address 0x4cb6180 is 12 bytes after a block of size 44 alloc'd
==23692==    at 0x482A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==23692==    by 0x1C14CD: node_new (regparse.c:1151)
==23692==    by 0x1C17D0: node_new_list (regparse.c:1291)
==23692==    by 0x1CD953: parse_branch (regparse.c:6377)
==23692==    by 0x1CD9BD: parse_subexp (regparse.c:6395)
==23692==    by 0x1CDB5D: parse_regexp (regparse.c:6443)
==23692==    by 0x1CDC80: onig_parse_make_tree (regparse.c:6485)
==23692==    by 0x1B27C6: onig_compile (regcomp.c:5739)
==23692==    by 0x1A0C20: onig_new_with_source (re.c:849)
==23692==    by 0x1A0CA8: make_regexp (re.c:873)
==23692==    by 0x1A479D: rb_reg_initialize (re.c:2546)
==23692==    by 0x1A4905: rb_reg_initialize_str (re.c:2571)
==23692== 
load-re.rb:2:in `initialize': premature end of char-class: /\/[\600000000000 (RegexpError)
\//
    from load-re.rb:2:in `new'
    from load-re.rb:2:in `block in <main>'
    from load-re.rb:1:in `open'
    from load-re.rb:1:in `<main>'
==23692== 
==23692== HEAP SUMMARY:
==23692==     in use at exit: 1,796,552 bytes in 27,452 blocks
==23692==   total heap usage: 52,413 allocs, 24,961 frees, 6,176,416 bytes allocated
==23692== 
==23692== LEAK SUMMARY:
==23692==    definitely lost: 289,615 bytes in 6,018 blocks
==23692==    indirectly lost: 341,542 bytes in 7,685 blocks
==23692==      possibly lost: 994,526 bytes in 9,609 blocks
==23692==    still reachable: 170,869 bytes in 4,140 blocks
==23692==         suppressed: 0 bytes in 0 blocks
==23692== Rerun with --leak-check=full to see details of leaked memory
==23692== 
==23692== For counts of detected and suppressed errors, rerun with: -v
==23692== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)


Files

load-re.rb (79 Bytes) load-re.rb grajagandev (David Moore), 05/24/2016 05:59 PM
overflow-next_state_value (15 Bytes) overflow-next_state_value grajagandev (David Moore), 05/24/2016 05:59 PM

Related issues

Related to Ruby master - Bug #12420: Regexp: Segfault due to Invalid Read in regparse.c : bbuf_free()ClosedActions

Associated revisions

Revision 05c631ee
Added by naruse (Yui NARUSE) about 3 years ago

  • regparse.c (fetch_token_in_cc): raise error if given octal escaped character is too big. [Bug #12420] [Bug #12423]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55163 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 55163
Added by naruse (Yui NARUSE) about 3 years ago

  • regparse.c (fetch_token_in_cc): raise error if given octal escaped character is too big. [Bug #12420] [Bug #12423]

Revision 55163
Added by naruse (Yui NARUSE) about 3 years ago

  • regparse.c (fetch_token_in_cc): raise error if given octal escaped character is too big. [Bug #12420] [Bug #12423]

Revision 55163
Added by naruse (Yui NARUSE) about 3 years ago

  • regparse.c (fetch_token_in_cc): raise error if given octal escaped character is too big. [Bug #12420] [Bug #12423]

Revision 55163
Added by naruse (Yui NARUSE) about 3 years ago

  • regparse.c (fetch_token_in_cc): raise error if given octal escaped character is too big. [Bug #12420] [Bug #12423]

Revision e45cf75f
Added by naruse (Yui NARUSE) about 3 years ago

  • re.c (unescape_nonascii): scan hex up to only 3 characters. [Bug #12420] [Bug #12423]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55165 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 55165
Added by naruse (Yui NARUSE) about 3 years ago

  • re.c (unescape_nonascii): scan hex up to only 3 characters. [Bug #12420] [Bug #12423]

Revision 55165
Added by naruse (Yui NARUSE) about 3 years ago

  • re.c (unescape_nonascii): scan hex up to only 3 characters. [Bug #12420] [Bug #12423]

Revision 55165
Added by naruse (Yui NARUSE) about 3 years ago

  • re.c (unescape_nonascii): scan hex up to only 3 characters. [Bug #12420] [Bug #12423]

Revision 55165
Added by naruse (Yui NARUSE) about 3 years ago

  • re.c (unescape_nonascii): scan hex up to only 3 characters. [Bug #12420] [Bug #12423]

Revision 1a7e2194
Added by usa (Usaku NAKAMURA) about 3 years ago

merge revision(s) 55163,55165: [Backport #12420] [Backport #12423]

    * regparse.c (fetch_token_in_cc): raise error if given octal escaped
      character is too big. [Bug #12420] [Bug #12423]

    * re.c (unescape_nonascii): scan hex up to only 3 characters.
      [Bug #12420] [Bug #12423]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@55363 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 55363
Added by usa (Usaku NAKAMURA) about 3 years ago

merge revision(s) 55163,55165: [Backport #12420] [Backport #12423]

* regparse.c (fetch_token_in_cc): raise error if given octal escaped
  character is too big. [Bug #12420] [Bug #12423]

* re.c (unescape_nonascii): scan hex up to only 3 characters.
  [Bug #12420] [Bug #12423]

Revision 68c4c9d2
Added by nagachika (Tomoyuki Chikanaga) about 3 years ago

merge revision(s) 55163,55165: [Backport #12420]

    * regparse.c (fetch_token_in_cc): raise error if given octal escaped
      character is too big. [Bug #12420] [Bug #12423]

    * re.c (unescape_nonascii): scan hex up to only 3 characters.
      [Bug #12420] [Bug #12423]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_3@55458 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 55458
Added by nagachika (Tomoyuki Chikanaga) about 3 years ago

merge revision(s) 55163,55165: [Backport #12420]

* regparse.c (fetch_token_in_cc): raise error if given octal escaped
  character is too big. [Bug #12420] [Bug #12423]

* re.c (unescape_nonascii): scan hex up to only 3 characters.
  [Bug #12420] [Bug #12423]

History

#1

Updated by naruse (Yui NARUSE) about 3 years ago

  • Status changed from Open to Closed

Applied in changeset r55163.


  • regparse.c (fetch_token_in_cc): raise error if given octal escaped character is too big. [Bug #12420] [Bug #12423]

Updated by usa (Usaku NAKAMURA) about 3 years ago

  • Backport changed from 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN to 2.1: WONTFIX, 2.2: REQUIRED, 2.3: REQUIRED
#3

Updated by usa (Usaku NAKAMURA) about 3 years ago

  • Related to Bug #12420: Regexp: Segfault due to Invalid Read in regparse.c : bbuf_free() added

Updated by usa (Usaku NAKAMURA) about 3 years ago

  • Backport changed from 2.1: WONTFIX, 2.2: REQUIRED, 2.3: REQUIRED to 2.1: WONTFIX, 2.2: DONE, 2.3: REQUIRED

ruby_2_2 r55363 merged revision(s) 55163,55165.

Updated by nagachika (Tomoyuki Chikanaga) about 3 years ago

  • Backport changed from 2.1: WONTFIX, 2.2: DONE, 2.3: REQUIRED to 2.1: WONTFIX, 2.2: DONE, 2.3: DONE

ruby_2_3 r55458 merged revision(s) 55163,55165.

Also available in: Atom PDF