Package: gnat-4.4
Version: 4.4.3-1
Severity: normal

Under some conditions, using GNAT.Expect.Non_Blocking_Spawn in
conjunction with GNAT.Expect.Close leads to memory corruption.

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-1.1 (lenny):
*** glibc detected *** ./obj/expect_test: double free or corruption
(!prev): 0x00000000006040a0 ***

* gnat 4.4.3-1 (unstable):
*** 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-1.1 (lenny):

#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

-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.26-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages gnat-4.4 depends on:
ii  gcc-4.4                   4.4.3-5        The GNU C compiler
ii  gnat-4.4-base             4.4.3-1        The GNU Compiler Collection (gnat
ii  libc6                     2.10.2-6       Embedded GNU C Library: Shared lib
ii  libc6-dev                 2.10.2-6       Embedded GNU C Library: Developmen
ii  libgcc1                   1:4.4.3-5      GCC support library
ii  libgmp3c2                 2:4.3.2+dfsg-1 Multiprecision arithmetic library
ii  libgnat-4.4               4.4.3-1        Runtime library for GNU Ada applic
ii  libgnatprj4.4             4.4.3-1        GNU Ada Project Manager
ii  libgnatvsn4.4             4.4.3-1        GNU Ada compiler version library
ii  libmpfr1ldbl              2.4.2-3        multiple precision floating-point

gnat-4.4 recommends no packages.

Versions of packages gnat-4.4 suggests:
pn  ada-reference-manual          <none>     (no description available)
pn  gnat-4.4-doc                  <none>     (no description available)

-- no debconf information



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to