bugGNU Octave - Bugs: bug #67249, ASAN problem with "test...

 
 

bug #67249: ASAN problem with "test ilu" on MacOS

Submitter:  Dmitri A. Sergatskov <dasergatskov>
Submitted:  Fri 27 Jun 2025 01:21:31 AM UTC
   
 
Category:  Interpreter Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Segfault, Bus Error, etc.
Status:  Fixed Assigned to:  None
Originator Name:  Open/Closed:  * Closed
Release:  * dev Release: 
Operating System:  * Mac OS Fixed Release:  10.3.0 (current stable)
Planned Release:  10.3.0 (current stable)
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Thu 10 Jul 2025 07:25:01 AM UTC, comment #6: 

Marking as Fixed and closing report.

Rik <rik5>
Group administrator
Wed 09 Jul 2025 08:14:39 PM UTC, comment #5: 

It looks fine. Besides the test I also run some examples off Matlab doc webpage and they all fine (small numerical discrepancies probably due to precision).

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Wed 09 Jul 2025 07:30:05 PM UTC, comment #4: 

I found another instance in the ilu code where using the modern C+11 form of std::set:erase() would simplify the code.  I also optimized some convoluted code with std::swap.  I checked everything in on the stable branch.  See cset 8591a26454e4.  The BIST tests pass, but it would be good if you could run one final test with ASAN to verify that the problem is gone.

Rik <rik5>
Group administrator
Sat 05 Jul 2025 08:36:27 PM UTC, comment #3: 

The attached patch fixed the crash for me.
Re-arranged the loop somewhat. Also "erase()" returns updated iterator, so we do not need to do it manually.

Dmitri.
--


(file #57367)

Dmitri A. Sergatskov <dasergatskov>
Sat 05 Jul 2025 08:08:58 PM UTC, comment #2: 

Yes, i am looking at the same and agree with you here. Also at the end:


 676                   w_data[jrow] = tl;
 677             }
 678           jrow = *(++it);
 679         }


Could it be past the end? Should we change it to:

-          jrow = *(++it);
+
+          it++;
+
+          if (it != iw_u.end ())
+            jrow = *it;
         }

       // Search for the pivot and update iw_l and iw_u if the pivot is not the


Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 05 Jul 2025 07:58:16 PM UTC, comment #1: 

I think this is real.  The stack trace says the read problem is with variable iw_u which is of type std::set.  I see two potential code problems.


Before the loop starts at _ilu_.cc:616


      it = iw_u.begin ();
      jrow = *it;


According to C++ standard, an iterator must not be dereferenced if the container is empty.  Maybe the code can guarantee that this is the case.  Otherwise, a check should be done first.

In the middle of the loop at _ilu_.cc:666


                  it2 = it;
                  it++;
                  iw_u.erase (it2);
                  jrow = *it;
                  continue;


This is just wrong.  Erasing an element invalidates all iterators on a container. 


Rik <rik5>
Group administrator
Fri 27 Jun 2025 01:21:31 AM UTC, original submission:  

On MacOS (homebrew) doing "test ilu" results in ASAN crash:

***** shared A
 A = sparse ([0 0 4 3 1; 5 1 2.3 2 4.5; 0 0 0 2 1;0 0 8 0 2.2; 0 0 9 9 1 ]);
***** test
 opts.udiag = 1;
 opts.type = "ilutp";
 opts.droptol = 0.2;
 [L, U, P] = ilu (A, opts);
 assert (norm (U, "fro"), 17.4577, 1e-4);
 assert (norm (L, "fro"), 2.4192, 1e-4);
=================================================================
==59078==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x00016bbe7cc8 at pc 0x000107c96914 bp 0x00016bbe78d0 sp 0x00016bbe78c8
READ of size 8 at 0x00016bbe7cc8 thread T0
    #0 0x000107c96910 in void octave::ilu_tp<SparseMatrix, double>(SparseMatrix&, SparseMatrix&, SparseMatrix&, long long, long long, double*, Array<long long, std::__1::allocator<long long>>&, double, double, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, double) __ilu__.cc
    #1 0x000107c8fa20 in octave::F__ilutp__(octave_value_list const&, int) __ilu__.cc:937
    #2 0x000107bdc828 in octave::tree_evaluator::execute_builtin_function(octave_builtin&, int, octave_value_list const&) pt-eval.cc:3555
    #3 0x000107973f04 in octave_function::call(octave::tree_evaluator&, int, octave_value_list const&) ov-fcn.cc:86
    #4 0x000107c0df9c in octave::tree_index_expression::evaluate_n(octave::tree_evaluator&, int) pt-idx.cc:523
    #5 0x000107ba0394 in octave::tree_multi_assignment::evaluate_n(octave::tree_evaluator&, int) pt-assign.cc:199
    #6 0x000107ba35c4 in octave::tree_multi_assignment::evaluate(octave::tree_evaluator&, int) pt-assign.h:159
    #7 0x000107be30e8 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4078
    #8 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #9 0x000107be2f50 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4053
    #10 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #11 0x000107be4160 in octave::tree_evaluator::visit_switch_command(octave::tree_switch_command&) pt-eval.cc:4240
    #12 0x000107be2f50 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4053
    #13 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #14 0x000107bdedb4 in octave::tree_evaluator::execute_user_function(octave_user_function&, int, octave_value_list const&) pt-eval.cc:3804
    #15 0x000107a52a54 in octave_user_function::call(octave::tree_evaluator&, int, octave_value_list const&) ov-usr-fcn.cc:567
    #16 0x000107c0df9c in octave::tree_index_expression::evaluate_n(octave::tree_evaluator&, int) pt-idx.cc:523
    #17 0x000107ba0394 in octave::tree_multi_assignment::evaluate_n(octave::tree_evaluator&, int) pt-assign.cc:199
    #18 0x000107ba35c4 in octave::tree_multi_assignment::evaluate(octave::tree_evaluator&, int) pt-assign.h:159
    #19 0x000107be30e8 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4078
    #20 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #21 0x000107bdedb4 in octave::tree_evaluator::execute_user_function(octave_user_function&, int, octave_value_list const&) pt-eval.cc:3804
    #22 0x000107a52a54 in octave_user_function::call(octave::tree_evaluator&, int, octave_value_list const&) ov-usr-fcn.cc:567
    #23 0x000107c0df9c in octave::tree_index_expression::evaluate_n(octave::tree_evaluator&, int) pt-idx.cc:523
    #24 0x000107ba0394 in octave::tree_multi_assignment::evaluate_n(octave::tree_evaluator&, int) pt-assign.cc:199
    #25 0x000107bbe770 in octave::tree_evaluator::eval_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, bool, int&, int) pt-eval.cc:1072
    #26 0x000107bc0870 in octave::tree_evaluator::eval(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, int) pt-eval.cc:1134
    #27 0x000107b79150 in octave::Feval(octave::interpreter&, octave_value_list const&, int) oct-parse.yy:5979
    #28 0x000107bdc94c in octave::tree_evaluator::execute_builtin_function(octave_builtin&, int, octave_value_list const&) pt-eval.cc:3560
    #29 0x000107973f04 in octave_function::call(octave::tree_evaluator&, int, octave_value_list const&) ov-fcn.cc:86
    #30 0x000107c0df9c in octave::tree_index_expression::evaluate_n(octave::tree_evaluator&, int) pt-idx.cc:523
    #31 0x000107c104d0 in octave::tree_index_expression::evaluate(octave::tree_evaluator&, int) pt-idx.h:108
    #32 0x000107be30e8 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4078
    #33 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #34 0x000107be4694 in octave::tree_evaluator::visit_try_catch_command(octave::tree_try_catch_command&) pt-eval.cc:4278
    #35 0x000107be2f50 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4053
    #36 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #37 0x000107be2f50 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4053
    #38 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #39 0x000107be5f04 in octave::tree_evaluator::visit_unwind_protect_command(octave::tree_unwind_protect_command&) pt-eval.cc:4423
    #40 0x000107be2f50 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4053
    #41 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #42 0x000107bd94c0 in void octave::tree_evaluator::execute_range_loop<double>(octave::range<double, void> const&, int, octave::octave_lvalue&, octave::tree_statement_list*) pt-eval.cc:3219
    #43 0x000107bd7994 in octave::tree_evaluator::visit_simple_for_command(octave::tree_simple_for_command&) pt-eval.cc:3266
    #44 0x000107be2f50 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4053
    #45 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #46 0x000107bdedb4 in octave::tree_evaluator::execute_user_function(octave_user_function&, int, octave_value_list const&) pt-eval.cc:3804
    #47 0x000107a52a54 in octave_user_function::call(octave::tree_evaluator&, int, octave_value_list const&) ov-usr-fcn.cc:567
    #48 0x000107c0df9c in octave::tree_index_expression::evaluate_n(octave::tree_evaluator&, int) pt-idx.cc:523
    #49 0x000107c104d0 in octave::tree_index_expression::evaluate(octave::tree_evaluator&, int) pt-idx.h:108
    #50 0x000107be30e8 in octave::tree_evaluator::visit_statement(octave::tree_statement&) pt-eval.cc:4078
    #51 0x000107be3d44 in octave::tree_evaluator::visit_statement_list(octave::tree_statement_list&) pt-eval.cc:4163
    #52 0x000107bbb8e8 in octave::tree_evaluator::eval(std::__1::shared_ptr<octave::tree_statement_list>&, bool) pt-eval.cc:1004
    #53 0x000107bbc9e4 in octave::tree_evaluator::repl() pt-eval.cc:821
    #54 0x0001084dd2ac in octave::interpreter::execute() interpreter.cc:898
    #55 0x000104209ad4 in main main-cli.cc:150
    #56 0x00019f7fab94 in start+0x17b8 (dyld:arm64e+0xfffffffffff3ab94)

Address 0x00016bbe7cc8 is located in stack of thread T0 at offset 1000 in frame
    #0 0x000107c930b8 in void octave::ilu_tp<SparseMatrix, double>(SparseMatrix&, SparseMatrix&, SparseMatrix&, long long, long long, double*, Array<long long, std::__1::allocator<long long>>&, double, double, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, double) __ilu__.cc:533

  This frame has 34 object(s):
    [32, 40) 'ref.tmp.i1832'
    [64, 72) 'ref.tmp.i1817'
    [96, 104) 'ref.tmp.i1795'
    [128, 136) 'ref.tmp.i'
    [160, 192) 'ref.tmp' (line 547)
    [224, 272) 'cidx_out_l' (line 565)
    [304, 320) 'ref.tmp36' (line 565)
    [336, 384) 'ridx_out_l' (line 567)
    [416, 432) 'ref.tmp47' (line 567)
    [448, 496) 'data_out_l' (line 569)
    [528, 544) 'ref.tmp59' (line 569)
    [560, 608) 'cidx_out_u' (line 573)
    [640, 656) 'ref.tmp73' (line 573)
    [672, 720) 'ridx_out_u' (line 575)
    [752, 768) 'ref.tmp88' (line 575)
    [784, 832) 'data_out_u' (line 577)
    [864, 880) 'ref.tmp102' (line 577)
    [896, 920) 'iw_l' (line 583)
    [960, 984) 'iw_u' (line 584) <== Memory access at offset 1000 overflows this variable
    [1024, 1040) 'ref.tmp496' (line 772) <== Memory access at offset 1000 underflows this variable
    [1056, 1072) 'ref.tmp508' (line 774)
    [1088, 1104) 'ref.tmp538' (line 781)
    [1120, 1136) 'ref.tmp550' (line 783)
    [1152, 1184) 'diag' (line 833)
    [1216, 1248) 'ref.tmp668' (line 842)
    [1280, 1312) 'ref.tmp680' (line 843)
    [1344, 1376) 'ref.tmp692' (line 849)
    [1408, 1440) 'ref.tmp703' (line 850)
    [1472, 1504) 'ref.tmp791' (line 899)
    [1536, 1568) 'agg.tmp.ensured'
    [1600, 1632) 'ref.tmp801' (line 901)
    [1664, 1696) 'ref.tmp802' (line 901)
    [1728, 1736) 'ref.tmp803' (line 901)
    [1760, 1792) 'ref.tmp827' (line 902)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow __ilu__.cc in void octave::ilu_tp<SparseMatrix, double>(SparseMatrix&, SparseMatrix&, SparseMatrix&, long long, long long, double*, Array<long long, std::__1::allocator<long long>>&, double, double, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, double)
Shadow bytes around the buggy address:
  0x00016bbe7a00: f2 f2 f8 f8 f2 f2 00 00 00 00 00 00 f2 f2 f2 f2
  0x00016bbe7a80: f8 f8 f2 f2 00 00 00 00 00 00 f2 f2 f2 f2 f8 f8
  0x00016bbe7b00: f2 f2 00 00 00 00 00 00 f2 f2 f2 f2 f8 f8 f2 f2
  0x00016bbe7b80: 00 00 00 00 00 00 f2 f2 f2 f2 f8 f8 f2 f2 00 00
  0x00016bbe7c00: 00 00 00 00 f2 f2 f2 f2 f8 f8 f2 f2 00 00 00 f2
=>0x00016bbe7c80: f2 f2 f2 f2 00 00 00 f2 f2[f2]f2 f2 f8 f8 f2 f2
  0x00016bbe7d00: f8 f8 f2 f2 f8 f8 f2 f2 f8 f8 f2 f2 f8 f8 f8 f8
  0x00016bbe7d80: f2 f2 f2 f2 f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 f8 f8
  0x00016bbe7e00: f2 f2 f2 f2 f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 f8 f8
  0x00016bbe7e80: f2 f2 f2 f2 f8 f8 f8 f8 f2 f2 f2 f2 00 00 00 00
  0x00016bbe7f00: f2 f2 f2 f2 f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 f8 f8
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==59078==ABORTING
fatal: caught signal Abort trap: 6 -- stopping myself...


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 #57367:  das_ilu_v1.diff added by dasergatskov (1KiB - 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 6 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2025-07-10 rik5 StatusReady For Test Fixed
        Open/ClosedOpen Closed
    2025-07-09 rik5 StatusNone Ready For Test
        Fixed ReleaseNone 10.3.0 (current stable)
        Planned ReleaseNone 10.3.0 (current stable)
    2025-07-05 dasergatskov Attached File- Added das_ilu_v1.diff, #57367

    Back to the top

    Powered by Savane 3.15-e6e5.
    Corresponding source code