Project

General

Profile

Actions

Bug #12423

closed

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

Added by grajagandev (David Moore) over 8 years ago. Updated over 8 years ago.

Status:
Closed
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 1 (0 open1 closed)

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

Updated by naruse (Yui NARUSE) over 8 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) over 8 years ago

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

Updated by usa (Usaku NAKAMURA) over 8 years ago

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

Updated by usa (Usaku NAKAMURA) over 8 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) over 8 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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0