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

 
 

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

Submitter:  Dmitri A. Sergatskov <dasergatskov>
Submitted:  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
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

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>
Group 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>
Group 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>
Group 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>
Group 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)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group 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.13-d3ae.
    Corresponding source code