https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69779

            Bug ID: 69779
           Summary: [6 Regression] Invalid free in driver::finalize on
                    s390x running libgccjit
           Product: gcc
           Version: 6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: driver
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dmalcolm at gcc dot gnu.org
  Target Milestone: ---
              Host: s390x-ibm-linux-gnu
            Target: s390x-ibm-linux-gnu
             Build: s390x-ibm-linux-gnu

I'm seeing crashes running "make check-jit" on s390x-ibm-linux-gnu:
e.g. *** Error in
`/home/dmalcolm/gcc-bugfixing/build/gcc/testsuite/jit/test-volatile.c.exe':
free(): invalid pointer: 0x000003fffdf30568 ***

The problem seems to be this line in driver::finalize:

#4  0x000003fffcfe4582 in driver::finalize (this=<optimized out>) at
../../src/gcc/gcc.c:9901
9901      XDELETEVEC (specs);

where specs == static_specs i.e. we have an attempt to free a
statically-allocated array.

specs is modified by this code in set_specs:
1871      /* See if the spec already exists.  */
1872      for (sl = specs; sl; sl = sl->next)
1873        if (name_len == sl->name_len && !strcmp (sl->name, name))
1874          break;
1875    
1876      if (!sl)
1877        {
1878          /* Not found - make it.  */
1879          sl = XNEW (struct spec_list);
1880          sl->name = xstrdup (name);
1881          sl->name_len = name_len;
1882          sl->ptr_spec = &sl->ptr;
1883          sl->alloc_p = 0;
1884          *(sl->ptr_spec) = "";
1885          sl->next = specs;
1886          sl->default_ptr = NULL;
1887          specs = sl;
1888        }

i.e. it only changes "specs" from static_specs if there's a set_spec for a name
that isn't in the static specs.

The cleanup code happens to work on x86_64 as we have two calls to set_spec
that modify "specs":

  (1) It becomes static_specs in first call to set_spec, within "read_specs":
    #0  set_spec (name=0x662131 "asm", 
    spec=0x6616e0 "%{m16|m32:--32}  %{m16|m32|mx32:;:--64}  %{mx32:--x32} 
%{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}",
user_p=false) at ../../src/gcc/gcc.c:1872

  (2) but then becomes non-equal in 2nd call to set_spec, also within
"read_specs"
     set_spec (name=0x664fd1 "cc1_cpu", 
    spec=0x65cb90 "%{march=native:%>march=native %:local_cpu_detect(arch)  
%{!mtune=*:%>mtune=native %:local_cpu_detect(tune)}}
%{mtune=native:%>mtune=native %:local_cpu_detect(tune)}", user_p=false) at
../../src/gcc/gcc.c:1890
  (and although there are many calls to set_spec, only those 2 modifiy "specs":
the first one, and cc1_cpu)

i.e. it only works for a host/target for which the "specs" file exists and has
a name of a spec that isn't in static_specs.

It fails on s390x since the specs file only has specs with the same names as
those in static_specs.

It looks like in driver::finalize that ought to be walking the list of
dynamically-allocated spec_list instances, freeing them, until we reach
static_specs.  Am testing a patch for this.

Reply via email to