bugGNU Octave - Bugs: bug #51533, heap-buffer-overflow in...

 
 

bug #51533: heap-buffer-overflow in Sparse.cc-tst

Submitted by:  Dmitri A. Sergatskov <dasergatskov>
Submitted on:  Sat 22 Jul 2017 12:00:11 AM UTC  
 
Category:  Interpreter Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Segfault, Bus Error, etc.
Status:  Fixed Assigned to:  None
Originator Name:  Dmitri A. Sergatskov Open/Closed:  Closed
Release:  dev Operating System:  GNU/Linux

Add a New Comment (Rich Markup)
   

You are not logged in

Please log in, so followups can be emailed to you.

 

( Jump to the original submission)

Mon 24 Jul 2017 03:53:42 AM UTC, comment #11: 

I cleaned up the patch to use more modern C++11 syntax and then pushed it here (http://hg.savannah.gnu.org/hgweb/octave/rev/10136bfd46a3).  Closing report.

Rik <rik5>
Project Administrator
Mon 24 Jul 2017 12:51:15 AM UTC, comment #10: 

With the patch applied it passes the test.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Mon 24 Jul 2017 12:36:30 AM UTC, comment #9: 

I reviewed lex.ll and the heap buffer overflow supposedly occurs with a read supposedly on this line of code.

function_text += "\n";

I suspect that it actually is the line before, but the error reporting is slightly off.

if (current_input_line[current_input_line.length () - 1] != '\n')

This could cause a problem if, for example, current_input_line was empty so that the length was 0.  In this case the index would be [-1] which could trigger this.

To debug this I modified the code slightly (there is a diff attached to the bug report).  Could you apply the diff with "patch -p1 < lex.diff", rebuild, and then run "test liboctave/array/Sparse.cc-tst" as before.  Even if it segfaults, I expect the diagnostics will be better and be localized to the 'char c' line.

diff -r f864950f837c libinterp/parse-tree/lex.ll
--- a/libinterp/parse-tree/lex.ll        Sun Jul 23 10:33:40 2017 -0700
+++ b/libinterp/parse-tree/lex.ll        Sun Jul 23 17:28:37 2017 -0700
@@ -3663,8 +3663,12 @@ namespace octave
         if (buffer_function_text)
           {
             function_text += current_input_line;
-            if (current_input_line[current_input_line.length () - 1] != '\n')
-              function_text += "\n";
+            if (current_input_line.length () > 0)
+              {
+                char c = current_input_line[current_input_line.length () - 1];
+                if (c != '\n')
+                  function_text += "\n";
+              }
           }
       }

(file #41308)

Rik <rik5>
Project Administrator
Sun 23 Jul 2017 12:31:27 AM UTC, comment #8: 

Attached.

Dmitri.
--

(file #41293)

Dmitri A. Sergatskov <dasergatskov>
Sun 23 Jul 2017 12:25:32 AM UTC, comment #7: 

I'm using gcc 5.4 which explains why I'm not getting the "stack-use-after-scope" warnings.

The first heap buffer overflow (from Sparse.cc-tst) is

READ of size 1 at 0x611000045eff thread T0
    #0 0x7f8f97a4cb7b in octave::lexer::fill_flex_buffer(char*, unsigned int) ../libinterp/parse-tree/lex.ll:3667

Could you upload lex.ll so that I can match the exact source code against the error report?

Rik <rik5>
Project Administrator
Sat 22 Jul 2017 06:00:55 PM UTC, comment #6: 

I think you need at least gcc 7 to get "stack-use-after-scope" diagnostic:

https://gcc.gnu.org/gcc-7/changes.html

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 22 Jul 2017 05:56:33 PM UTC, comment #5: 

On "test libinterp/octave-value/ov-class.cc-tst" I get

octave:1> test libinterp/octave-value/ov-class.cc-tst verbose
>>>>> /home/dima/src/octave/gcc_asan/libinterp/octave-value/ov-class.cc-tst
***** assert (class (1.1), "double")
***** assert (class (single (1.1)), "single")
***** assert (class (uint8 (1)), "uint8")
***** testif HAVE_JAVA; usejava ("jvm")
jobj = javaObject ("java.lang.StringBuffer");
assert (class (jobj), "java.lang.StringBuffer");
----- skipped test (missing feature)

***** error class ()
=================================================================
==2449==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffce2224500 at pc 0x7f6a440bce67 bp 0x7ffce2224200 sp 0x7ffce22241f0
WRITE of size 8 at 0x7ffce2224500 thread T0
    #0 0x7f6a440bce66 in Array<octave_value>::Array() ../liboctave/array/Array.h:257
    #1 0x7f6a440bce66 in octave_value_list::octave_value_list() ../libinterp/octave-value/ovl.h:46
    #2 0x7f6a4541ceb9 in octave::tree_evaluator::visit_identifier(octave::tree_identifier&) ../libinterp/parse-tree/pt-eval.cc:1035
    #3 0x7f6a453d8d2d in octave::tree_evaluator::evaluate(octave::tree_expression*, int) ../libinterp/parse-tree/pt-eval.h:270
  (...deleted...)

HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope ../liboctave/array/Array.h:257 in Array<octave_value>::Array()

which I assume is false positive per the HINT.
(I get this error in many tests).

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 22 Jul 2017 05:41:33 PM UTC, comment #4: 

../configure --disable-java --disable-docs --without-qt --without-fltk --enable-address-sanitizer-flags

   HG ID for this build is "d891b6a16a4d"

ASAN_OPTIONS=leak_check_at_exit=0:verbose=1 ./run-octave

'-fno-omit-frame-pointer' seems to help with diagnostic (gives line numbers). But the errors still there.


octave:1> test liboctave/array/Sparse.cc-tst
=================================================================
==1045==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x611000045eff at pc 0x7f8f97a4cb7c bp 0x7ffd8dfe6e90 sp 0x7ffd8dfe6e80
READ of size 1 at 0x611000045eff thread T0
    #0 0x7f8f97a4cb7b in octave::lexer::fill_flex_buffer(char*, unsigned int) ../libinterp/parse-tree/lex.ll:3667
    #1 0x7f8f97a548e8 in yy_get_next_buffer libinterp/parse-tree/lex.cc:3434
    #2 0x7f8f97a6c8a4 in octave_lex(OCTAVE_STYPE*, void*) libinterp/parse-tree/lex.cc:3274
    #3 0x7f8f97abf4b5 in octave_pull_parse(octave_pstate*, octave::base_parser&) libinterp/parse-tree/oct-parse.cc:2990
(...deleted... full log attached)

SUMMARY: AddressSanitizer: heap-buffer-overflow ../libinterp/parse-tree/lex.ll:3667 in octave::lexer::fill_flex_buffer(char*, unsigned int)

Also the same in

octave:1> test libinterp/octave-value/ov-fcn-handle.cc-tst verbose
>>>>> /home/dima/src/octave/gcc_asan/libinterp/octave-value/ov-fcn-handle.cc-tst
***** test <*33857>
a = 2;
f = @(x) a + x;
g = @(x) 2 * x;
hm = @version;
hdld = @svd;
hbi = @log2;
f2 = f;
g2 = g;
hm2 = hm;
hdld2 = hdld;
hbi2 = hbi;
modes = {"-text", "-binary"};
if (isfield (__octave_config_info__, "HAVE_HDF5")
     && __octave_config_info__ ("HAVE_HDF5"))
   modes(end+1) = "-hdf5";
endif
for i = 1:numel (modes)
   mode = modes{i};
   nm = tempname ();
   unwind_protect
     f2 (1);
     save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
     clear f2 g2 hm2 hdld2 hbi2
     load (nm);
     assert (f (2), f2 (2));
     assert (g (2), g2 (2));
     assert (g (3), g2 (3));
     unlink (nm);
     save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
   unwind_protect_cleanup
     unlink (nm);
   end_unwind_protect
endfor
***** function fcn_handle_save_recurse (n, mode, nm, f2, g2, hm2, hdld2, hbi2)
  if (n == 0)
    save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
  else
    fcn_handle_save_recurse (n - 1, mode, nm, f2, g2, hm2, hdld2, hbi2);
  endif
=================================================================
==1561==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x611000052bff at pc 0x7f75bf7f8b7c bp 0x7ffdc75d0990 sp 0x7ffdc75d0980
READ of size 1 at 0x611000052bff thread T0
    #0 0x7f75bf7f8b7b in octave::lexer::fill_flex_buffer(char*, unsigned int) ../libinterp/parse-tree/lex.ll:3667
    #1 0x7f75bf8008e8 in yy_get_next_buffer libinterp/parse-tree/lex.cc:3434
    #2 0x7f75bf8188a4 in octave_lex(OCTAVE_STYPE*, void*) libinterp/parse-tree/lex.cc:3274
    #3 0x7f75bf86b4b5 in octave_pull_parse(octave_pstate*, octave::base_parser&) libinterp/parse-tree/oct-parse.cc:2990
    #4 0x7f75bf86b658 in octave::parser::run() libinterp/parse-tree/oct-parse.yy:4286

(....deleted......)

and few others like that.

Dmitri.
--

(file #41291)

Dmitri A. Sergatskov <dasergatskov>
Sat 22 Jul 2017 05:07:35 PM UTC, comment #3: 

I built it without java, qt, and fltk.
I will try with '-enable-address-sanitizer-flags'.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 22 Jul 2017 05:02:44 PM UTC, comment #2: 

Instead of changing the CXXFLAGS manually, I configured with '-enable-address-sanitizer-flags'.  This also adds '-fno-omit-frame-pointer'.  I don't get a segfault in ov-fcn-handle.cc, but I do get one in test libinterp/octave-value/ov-class.cc-tst.  Using gdb, the problem seems to be within the Java JVM: /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/libjvm.so.

Rik <rik5>
Project Administrator
Sat 22 Jul 2017 12:28:38 AM UTC, comment #1: 

The same (?) problem shows up in some other tests:

octave:1> test libinterp/octave-value/ov-fcn-handle.cc-tst verbose
>>>>> /home/dima/src/octave/gcc_asan/libinterp/octave-value/ov-fcn-handle.cc-tst
***** test <*33857>
a = 2;
f = @(x) a + x;
g = @(x) 2 * x;
hm = @version;
hdld = @svd;
hbi = @log2;
f2 = f;
g2 = g;
hm2 = hm;
hdld2 = hdld;
hbi2 = hbi;
modes = {"-text", "-binary"};
if (isfield (__octave_config_info__, "HAVE_HDF5")
     && __octave_config_info__ ("HAVE_HDF5"))
   modes(end+1) = "-hdf5";
endif
for i = 1:numel (modes)
   mode = modes{i};
   nm = tempname ();
   unwind_protect
     f2 (1);
     save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
     clear f2 g2 hm2 hdld2 hbi2
     load (nm);
     assert (f (2), f2 (2));
     assert (g (2), g2 (2));
     assert (g (3), g2 (3));
     unlink (nm);
     save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
   unwind_protect_cleanup
     unlink (nm);
   end_unwind_protect
endfor
***** function fcn_handle_save_recurse (n, mode, nm, f2, g2, hm2, hdld2, hbi2)
  if (n == 0)
    save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
  else
    fcn_handle_save_recurse (n - 1, mode, nm, f2, g2, hm2, hdld2, hbi2);
  endif
=================================================================
==30622==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6110000535ff at pc 0x7fea234002ee bp 0x7fffb2456ef0 sp 0x7fffb2456ee0
...skip...
SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/dima/src/octave/gcc_asan/libinterp/.libs/liboctinterp.so.4+0x155e2ed) in octave::lexer::fill_flex_buffer(char*, unsigned int)

Dmitri A. Sergatskov <dasergatskov>
Sat 22 Jul 2017 12:00:11 AM UTC, original submission:  

compiled with fsanitize=address.
Running

test liboctave/array/Sparse.cc-tst

results in

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/dima/src/octave/gcc_asan/libinterp/.libs/liboctinterp.so.4+0x158d2d9) in octave::lexer::fill_flex_buffer(char*, unsigned int)

Full error log is attached.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #41308:  lex.diff added by rik5 (697B - text/x-patch)
file #41293:  lex.ll added by dasergatskov (100KiB - application/octet-stream)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by dasergatskov (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only project members can vote.

     

     

     

    Follow 8 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2017-07-24 rik5 StatusIn Progress => Fixed
        Open/ClosedOpen => Closed
    2017-07-24 rik5 Attached File- => Added lex.diff, #41308
        StatusWorks For Me => In Progress
    2017-07-23 dasergatskov Attached File- => Added lex.ll, #41293
    2017-07-22 dasergatskov Attached File- => Added sparse_overflow_err_2.txt, #41291
    2017-07-22 rik5 StatusNone => Works For Me
    2017-07-22 dasergatskov Attached File- => Added sparse_overflow_err.txt, #41285

    Back to the top


    Powered by Savane 3.5