bugGNU Octave - Bugs: bug #54415, The row_as_string( index ).c_str()...

 
 

bug #54415: The row_as_string( index ).c_str() method of the octave-4 charMatrix class fails for strings longer than 15 bytes

Submitter:  Alan W. Irwin <airwin>
Submitted:  Wed 01 Aug 2018 02:44:50 AM UTC
   
 
Category:  None Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Unexpected Error or Warning
Status:  Invalid / Not an Octave Bug Assigned to:  None
Originator Name:  Open/Closed:  * Closed
Release:  * 4.4.0 Operating System:  * GNU/Linux
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Thu 02 Aug 2018 07:04:09 AM UTC, comment #3: 

Thanks for reporting back.

Closing bug report as invalid.

Markus Mützel <mmuetzel>
Group administrator
Wed 01 Aug 2018 10:02:19 PM UTC, comment #2: 

Thanks, Markus, for that useful advice.  Indeed, when I changed

tmp_cstring = (char *) temp_matrix.row_as_string( i ).c_str();
   
(where the tmp_cstring declaration was properly scoped)
   
to
   
str         = temp_matrix.row_as_string( i );
tmp_cstring = (char *) str.c_str();
   
(where both the str and tmp_cstring declarations were properly scoped)
   
in our own implemented swig typemap for the swig-generated octave bindings for both hex_print2 and various PLplot functions that have const char ** arguments, all problems with long strings went away.  For example:

octave:3> hex_print2(["0123456789abcde"; "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"])
30 31 32 33 34 35 36 37 38 39 61 62 63 64 65  0
0123456789abcde
30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66  0
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

now works fine.  Also, the previous success for our swig-generated bindings for the conversion of cell arrays of long strings is now explained because that interface code always used the preferred style.

Thanks, once again for your key help in solving this issue, and please close this bug with appropriate labels indicating not a direct octave issue but solved anyway.

Alan W. Irwin <airwin>
Wed 01 Aug 2018 09:08:00 AM UTC, comment #1: 

This might be a similar issue to the one discovered in bug #54299.

Recently, gcc seems to have changed the lifetime of temporary strings that are not assigned to a variable. It looks like the C++ string returned by "row_as_string" is destroyed immediately after is is created. Thus, the reference to the C string array returned by "c_str" gets invalid. The memory at that location is no longer protected from being overwritten. The results of dereferencing that pointer is undefined.

You might be able to fix your code by explicitly assigning the C++ string returned by "row_as_string" to a variable for which you can control the scope.
I think there is nothing that Octave can do to influence that behavior.

Please report back if that fixes the issue.

Markus Mützel <mmuetzel>
Group administrator
Wed 01 Aug 2018 02:44:50 AM UTC, original submission:  

I have attached a simple self-contained project that demonstrates that the row_as_string( index ).c_str() method of the octave-4 charMatrix class for converting non-cell octave arrays of UTF-8 strings to C strings fails if the number of bytes in the UTF-8 string exceeds 15 but succeeds otherwise.  Note this simple project uses the same interfacing method to transform octave arrays of UTF-8 strings to C strings that is used to implement the octave binding for PLplot and also mimics the bad PLplot results in this regard for octave-4 for strings longer than 15 characters that did not occur for PLplot with octave 3.8.x.  Please follow the README of the attached project to build (with help from swig) a simple Oct-file that can be loaded from Octave to demonstrate the problem.

If you run octave with gdb, then the peculiar nature of this problem for the octave non-cell array

["0123456789abcdef"]

(whose length is one more than the limit of 15) is exposed where a first call to the row_as_string( index ).c_str() method fails, but if you execute it again under gdb the old char pointer contents is correctly updated! Here is the part of a gdb session that demonstrates this peculiarity:

Thread 18 "QThread" hit Breakpoint 2, _wrap_hex_print2 (args=..., nargout=0)
    at /home/software/plplot/HEAD/test_octave/hex_print/build_dir/hex_printOCTAVE_wrap.cxx:2728
2728              tmp_cstring = (char *) temp_matrix.row_as_string( i ).c_str();
(gdb) list 2728
2723              }
2724            }
2725            else
2726            {
2727              tmp_cstring = NULL;
2728              tmp_cstring = (char *) temp_matrix.row_as_string( i ).c_str();
2729              if( !tmp_cstring )
2730              {
2731                // For this failure adjust Alen to only delete previously defined arg2[i].
2732                Alen = i;
(gdb) print tmp_cstring
$1 = 0x0
(gdb) next
2729              if( !tmp_cstring )
(gdb) print temp_matrix
$2 = {<charNDArray> = {<Array<char>> = {_vptr.Array = 0x7ffff7dca830 <vtable for charMatrix+16>, dimensions = {
        rep = 0x7fffa81d3f10}, rep = 0x7fffa83dd910, slice_data = 0x7fffa81c26d0 "0123456789abcdef ",
      slice_len = 16}, <No data fields>}, <No data fields>}
(gdb) print tmp_cstring
$3 = 0x7fffa81cbf40 ""
(gdb) print temp_matrix.row_as_string( i, false ).c_str()
$4 = 0x7fffa81cbf40 "0123456789abcdef"
(gdb) print tmp_cstring
$5 = 0x7fffa81cbf40 "0123456789abcdef"

So the $2 result shows that the temp_matrix object contains "0123456789abcdef" in slice_data, but the $3 result shows the call of that method for this string with 16 characters does not find that string and and gives a zero-length string instead.  However, $4 and $5 show if the method is called again (from gdb with the default second false argument specified since gdb demands default arguments are specified), the contents of tmp_cstring are updated to the correct value!  I could not replicate this behaviour by calling the method twice in the code.  But in any case, gdb calling the method a second time with no reference to tmp_cstring somehow updates the contents of the location of the area pointed to by tmp_cstring from the first call to the method.  This appears to indicate that the method somehow keeps track of old locations it has generated and given the right circumstances will update those correctly after not doing that properly the first time the method is called!

N.B. I haven't labelled this bug report as a regression, but I am virtually positive the issue demonstrated by the attached project as well as the above peculiar gdb behaviour is a regression against octave-3.8.x because I did not encounter the corresponding PLplot issue for that (Debian Jessie) version of octave.  Although I am not in position to prove that regression myself using the simple attached project (because I no longer have access to octave-3.8.x because I have updated to Debian Buster), I suggest for those who do have such access it should be straightforward to prove the regression using the attached project.  And, of course, if the regression is proved that way it should be straightforward to bisect to find the commit where the regression was first introduced.

Alan W. Irwin <airwin>

 

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

Attach Files:
   
   
Comment:
   

Attached Files
file #44678:  hex_print.tar.gz added by airwin (7KiB - application/gzip - Simple project to build an Oct-file that demonstrates the issue)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by mmuetzel (Posted a comment)
  • -email is unavailable- added by airwin (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 3 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2018-08-02 mmuetzel StatusNone Invalid / Not an Octave Bug
        Open/ClosedOpen Closed
    2018-08-01 airwin Attached File- Added hex_print.tar.gz, #44678

    Back to the top

    Powered by Savane 3.13-d3ae.
    Corresponding source code