(forwarding Debian bug #575954) Under some conditions, using GNAT.Expect.Non_Blocking_Spawn in conjunction with GNAT.Expect.Close leads to memory corruption on amd64.
Given the following small reproducer: -- expect_test.adb with Ada.Text_IO; with GNAT.Expect; with GNAT.OS_Lib; with GNAT.Regpat; procedure Expect_Test is use GNAT.Expect; Fd : Process_Descriptor; Command : constant String := "./print_file"; Arg_List : GNAT.OS_Lib.Argument_List (1 .. 0); Result : Expect_Match; Match : GNAT.Regpat.Match_Array (0 .. 0); begin Non_Blocking_Spawn (Descriptor => Fd, Command => Command, Args => Arg_List, Buffer_Size => 128, Err_To_Out => True); Expect (Descriptor => Fd, Result => Result, Regexps => Regexp_Array' (+"END TESTS(.*)FAILED", +"END TESTS(.*)PASSED"), Matched => Match, Timeout => 100000); Ada.Text_IO.Put_Line ("Terminated"); Ada.Text_IO.Put_Line (Expect_Out (Descriptor => Fd)); Ada.Text_IO.Put_Line ("Buffer len " & Expect_Out (Descriptor => Fd)'Length'Img); Close (Descriptor => Fd); exception when Process_Died => Ada.Text_IO.Put_Line ("Process died"); Ada.Text_IO.Put_Line (Expect_Out (Descriptor => Fd)); Close (Descriptor => Fd); end Expect_Test; -- print_file.adb with Ada.Text_IO; procedure Print_File is Filename : constant String := "output"; File : Ada.Text_IO.File_Type; begin Ada.Text_IO.Open (File => File, Mode => Ada.Text_IO.In_File, Name => Filename); while not Ada.Text_IO.End_Of_File (File => File) loop delay 0.001; Ada.Text_IO.Put_Line (Ada.Text_IO.Get_Line (File => File)); end loop; Ada.Text_IO.Close (File => File); end Print_File; -- output .................................................................... .................................................................... .................................................................... END TESTS...................................................: PASSED -- Running the expect_test binary on amd64 results in memory corruption. As it seems this only happens if the following conditions are met: * the binary spawned produces more output than the expect buffer size This should not matter because Non_Blocking_Spawn is expected to discard old characters: "The expect buffer associated with that process can contain at most Buffer_Size characters. Older characters are simply discarded when this buffer is full." * the spawned binary uses file IO * the code sleeps between the text output cycles Tests: * gnat 4.3.2: *** glibc detected *** ./obj/expect_test: double free or corruption (!prev): 0x00000000006040a0 *** * gnat 4.4.3: *** glibc detected *** ./obj/expect_test: free(): invalid next size (fast): 0x0000000000605090 *** The bug is also present with the tip of the gcc-4_4-branch (Subversion revision 157750) from upstream (verified by Ludovic Brenta). Full gdb backtrace with gnat 4.3.2: #0 0x00007f9502737ed5 in raise () from /lib/libc.so.6 No symbol table info available. #1 0x00007f95027393f3 in abort () from /lib/libc.so.6 No symbol table info available. #2 0x00007f9502774388 in __libc_message () from /lib/libc.so.6 No symbol table info available. #3 0x00007f9502779928 in malloc_printerr () from /lib/libc.so.6 No symbol table info available. #4 0x00007f950277ba36 in free () from /lib/libc.so.6 No symbol table info available. #5 0x00007f9502ee53a5 in <__gnat_free> (ptr=6308000) at s-memory.adb:117 No locals. #6 0x00007f9502e670af in gnat.expect.close (descript...@0x7fffffffbe50) at g-expect.adb:227 current_filter = <value optimized out> next_filter = <value optimized out> #7 0x0000000000402ff7 in _ada_expect_test () No locals. The complete reproducer code can be downloaded at [1]. - reto [1] - http://www.codelabs.ch/~reet/reproducers/gnat-expect.tar.bz2 -- Summary: GNAT.Expect.Non_Blocking_Spawn double free or corruption Product: gcc Version: 4.4.4 Status: UNCONFIRMED Severity: normal Priority: P3 Component: ada AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: reet at codelabs dot ch GCC build triplet: x86_64-linux-gnu GCC host triplet: x86_64-linux-gnu GCC target triplet: x86_64-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43598