Bug 56659 - Segfault due to missing libcpp error handler for "gfortran -cpp"
Summary: Segfault due to missing libcpp error handler for "gfortran -cpp"
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-invalid-code
Depends on: 62226
Blocks:
  Show dependency treegraph
 
Reported: 2013-03-20 07:29 UTC by Tobias Burnus
Modified: 2021-10-08 07:58 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-03-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2013-03-20 07:29:14 UTC
Reported by Paul Kapinos at fortran@gcc,
http://thread.gmane.org/gmane.comp.gcc.fortran/40495
http://gcc.gnu.org/ml/fortran/2013-03/msg00083.html

The problem is that libcpp calls an error handler, which is not set in f951.


Namely,   pfile->cb.error == NULL  but should be point to a function; it has the the prototype:
 bool (*)(cpp_reader *, int, int, source_location, unsigned int, const char *,
          va_list *) 
C/C++ use:
   in c-opts.c: "cb->error = c_cpp_error;"
the function is declared in c-family/c-common.c.


Test case:
* mkdir -p foo/bar
* chmod 000 foo
* gfortran -cpp some_file.F90
Comment 1 Richard Biener 2013-03-20 10:49:24 UTC
Confirmed.
Comment 2 Manuel López-Ibáñez 2015-09-13 15:57:40 UTC
(In reply to Tobias Burnus from comment #0)
> Reported by Paul Kapinos at fortran@gcc,
> http://thread.gmane.org/gmane.comp.gcc.fortran/40495
> http://gcc.gnu.org/ml/fortran/2013-03/msg00083.html
> 
> The problem is that libcpp calls an error handler, which is not set in f951.
> 
> 
> Namely,   pfile->cb.error == NULL  but should be point to a function; it has
> the the prototype:
>  bool (*)(cpp_reader *, int, int, source_location, unsigned int, const char
> *,
>           va_list *) 
> C/C++ use:
>    in c-opts.c: "cb->error = c_cpp_error;"
> the function is declared in c-family/c-common.c.

Now that Fortran uses the common diagnostics machinery, it should be possible to either move this function to common code or create a duplicate in the Fortran FE.

(Even better would be to convert the common diagnostics machinery to a library and make libcpp depend on it, which will avoid all these conversions from/to libcpp/FE enums since libcpp could use directly the same diagnostic enums as the rest of the compiler)
Comment 3 Manuel López-Ibáñez 2015-09-13 16:00:16 UTC
(In reply to Manuel López-Ibáñez from comment #2)
> Now that Fortran uses the common diagnostics machinery, it should be
> possible to either move this function to common code or create a duplicate
> in the Fortran FE.

For this function to work, CPP options used by Fortran must be specially encoded in the *.opt file. See bug 62226.
Comment 4 Tobias Burnus 2021-09-24 07:54:56 UTC
I think this issue is already fixed for a while.

An issue related to the callback init coming too late for libcpp / incpath.c's call has been fixed by the first of the second commit in PR 55534 – However, for the issue reported in this PR, the callbacks were already initialized before the PR55534 fix.

Hence close as FIXED.
Comment 5 Paul 2021-10-06 11:22:30 UTC
Just tried all versions of gfortran available up to 10.2.0: the very same 'internal compiler error' is still reported using the initial reproducer. 

May that be connected to the old Linux we're using (CentOS 7.8)? 

pk224850@linuxc2:~/bugreports/GCC/007-ICE_unavailbale_Idir[524]$ ./runme007.sh              
mkdir: cannot create directory ‘foo’: Permission denied
------------------------------------------------------------------------------
f951: Warning: Include directory ‘./foo/bar’: Permission denied
f951: internal compiler error: in cpp_diagnostic_at, at libcpp/errors.c:41
0x14f3468 cpp_diagnostic_at
        ../../../SOURCES/gcc-10.2.0/libcpp/errors.c:41
0x14f3468 cpp_diagnostic_at
        ../../../SOURCES/gcc-10.2.0/libcpp/errors.c:34
0x14f3468 cpp_diagnostic
        ../../../SOURCES/gcc-10.2.0/libcpp/errors.c:75
0x14f34f9 cpp_error(cpp_reader*, cpp_diagnostic_level, char const*, ...)
        ../../../SOURCES/gcc-10.2.0/libcpp/errors.c:89
0x9d5326 remove_duplicates
        ../../../SOURCES/gcc-10.2.0/gcc/incpath.c:260
0x9d58c9 merge_include_chains
        ../../../SOURCES/gcc-10.2.0/gcc/incpath.c:371
0x9d58c9 register_include_chains(cpp_reader*, char const*, char const*, char const*, int, int, int)
        ../../../SOURCES/gcc-10.2.0/gcc/incpath.c:498
0x654169 gfc_cpp_register_include_paths()
        ../../../SOURCES/gcc-10.2.0/gcc/fortran/cpp.c:722
0x654169 gfc_cpp_post_options()
        ../../../SOURCES/gcc-10.2.0/gcc/fortran/cpp.c:494
0x6c8b50 gfc_post_options(char const**)
        ../../../SOURCES/gcc-10.2.0/gcc/fortran/options.c:488
0x63044a process_options
        ../../../SOURCES/gcc-10.2.0/gcc/toplev.c:1384
0x63044a do_compile
        ../../../SOURCES/gcc-10.2.0/gcc/toplev.c:2200
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
------------------------------------------------------------------------------
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/local_rwth/sw/gcc/10.2.0/libexec/gcc/x86_64-pc-linux-gnu/10.2.0/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
Target: x86_64-pc-linux-gnu
Configured with: ../../SOURCES/gcc-10.2.0/configure --prefix=/usr/local_rwth/sw/gcc/10.2.0 --enable-offload-targets=nvptx-none --enable-languages=c,c++,objc,obj-c++,fortran --enable-lto --enable-install-libiberty --with-gmp=/w0/tmp/pk224850/GCC/build/destdir/usr/local_rwth/sw/gcc/10.2.0 --with-mpfr=/w0/tmp/pk224850/GCC/build/destdir/usr/local_rwth/sw/gcc/10.2.0 --with-mpc=/w0/tmp/pk224850/GCC/build/destdir/usr/local_rwth/sw/gcc/10.2.0 --with-ppl=/w0/tmp/pk224850/GCC/build/destdir/usr/local_rwth/sw/gcc/10.2.0 --with-isl --with-default-libstdcxx-abi=gcc4-compatible LDFLAGS='-Wl,-rpath,/usr/local_rwth/sw/gcc/10.2.0/lib64 -Wl,-rpath,/usr/local_rwth/sw/gcc/10.2.0/lib'
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.2.0 (GCC)
Comment 6 Tobias Burnus 2021-10-06 21:23:05 UTC
(In reply to Paul from comment #5)
> Just tried all versions of gfortran available up to 10.2.0: the very same
> 'internal compiler error' is still reported using the initial reproducer. 

Can you share the initial reproducer? The email link to gmane no longer works and what is written in the the original description and in the other email lacks the details. It only has:

Test case:
* mkdir -p foo/bar
* chmod 000 foo
* gfortran -cpp some_file.F90

But that obviously does not use 'foo/bar' at all.

I have no idea what's in 'some_file.F90'; the most straight-forward input would be:
  echo '#include "foo/bar/file.f90"' > some_file.F90
but when I try this, GCC 7, 8, 9, 10 of Ubuntu and the current development version all show the same:
  some_file.F90:2:2:
  Fatal Error: foo/bar/file.f90: Permission denied

(The off-by-one line number issue is PR 100904.)

I assume that your file contains something different - but what? Can you enlighten me?

 * * *

A couple of fixes were done in the development branch (to be released as GCC 12 around April), cf. PR 55534.
Comment 7 kapinos 2021-10-07 07:50:12 UTC
Sorry, for not adding the reproducer again. It is very K.I.S.S.:

- make (or reuse) an dir w/o read permissions
- use it as include dir at *any* Fortran source including empty ones.

The output of gfortran 10.2.0 was added previously, cf.
 > f951: Warning: Include directory ‘./foo/bar’: Permission denied
 > f951: internal compiler error: in cpp_diagnostic_at, at libcpp/errors.c:41
.......




$ cat runme007.sh
mkdir -p foo/bar
chmod 000 foo
echo "-------------------------------------------------------------------------"
gfortran -c  -I./foo/bar mini.F90
echo "------------------------------------------------------------------------"
gfortran -v

$ cat mini.F90
program mini
end







On 10/6/21 11:23 PM, burnus at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56659
> 
> --- Comment #6 from Tobias Burnus <burnus at gcc dot gnu.org> ---
> (In reply to Paul from comment #5)
>> Just tried all versions of gfortran available up to 10.2.0: the very same
>> 'internal compiler error' is still reported using the initial reproducer.
> 
> Can you share the initial reproducer? The email link to gmane no longer works
> and what is written in the the original description and in the other email
> lacks the details. It only has:
> 
> Test case:
> * mkdir -p foo/bar
> * chmod 000 foo
> * gfortran -cpp some_file.F90
> 
> But that obviously does not use 'foo/bar' at all.
> 
> I have no idea what's in 'some_file.F90'; the most straight-forward input would
> be:
>    echo '#include "foo/bar/file.f90"' > some_file.F90
> but when I try this, GCC 7, 8, 9, 10 of Ubuntu and the current development
> version all show the same:
>    some_file.F90:2:2:
>    Fatal Error: foo/bar/file.f90: Permission denied
> 
> (The off-by-one line number issue is PR 100904.)
> 
> I assume that your file contains something different - but what? Can you
> enlighten me?
> 
>   * * *
> 
> A couple of fixes were done in the development branch (to be released as GCC 12
> around April), cf. PR 55534.
>
Comment 8 Tobias Burnus 2021-10-07 10:44:45 UTC
(In reply to kapinos from comment #7)
> The output of gfortran 10.2.0 was added previously, cf.
>  > f951: Warning: Include directory ‘./foo/bar’: Permission denied
>  > f951: internal compiler error: in cpp_diagnostic_at, at libcpp/errors.c:41

I can reproduce this with GCC 7 to 10. But with my patch for PR 100904 (see commit there), this is fixed in GCC 12:

  f951: Warning: Include directory ‘foo/bar/’: Permission denied
  <built-in>: Error: foo/bar: Permission denied

(The <built-in> shows up when entering a file but the file is not yet there. Not ideal,
but not that quick to fix. Once the file is read, that's replaced by the file name and line number. Still, the <built-in> issue should be fixed eventually.)
Comment 9 Manuel López-Ibáñez 2021-10-08 07:09:43 UTC
(In reply to Tobias Burnus from comment #8)
>   f951: Warning: Include directory ‘foo/bar/’: Permission denied
>   <built-in>: Error: foo/bar: Permission denied
> 
> (The <built-in> shows up when entering a file but the file is not yet there.
> Not ideal,
> but not that quick to fix. Once the file is read, that's replaced by the
> file name and line number. Still, the <built-in> issue should be fixed
> eventually.)

Hi Tobias,

Are you sure the Error is produced *after* entering the file (by entering I mean pushing the file into the include stack and thus updating the line-map). If so, then the line-maps are not correctly named and the diagnostic wants to print some filename but the line-map or the include stack says that the name of the file is <built-in>.

But it could also be that the Error is produced *before* entering the file. Then, the bug is that something else has pushed the <built-in> context into the line-map stack. This should be command-line context and produce:

f951: Error: foo/bar: Permission denied

or:

<command-line>: Error: foo/bar: Permission denied

In either case, this points to some mess in the line-map stack.
Comment 10 Tobias Burnus 2021-10-08 07:58:58 UTC
(In reply to Manuel López-Ibáñez from comment #9)
> (In reply to Tobias Burnus from comment #8)
> >   f951: Warning: Include directory ‘foo/bar/’: Permission denied
> >   <built-in>: Error: foo/bar: Permission denied
> > (The <built-in> 
>
> Are you sure the Error is produced *after* entering the file (by entering I
> mean pushing the file into the include stack and thus updating the
> line-map).

I was too brief. It occurs between the two. The full version is:

If everything is not on the file stack 'f951' is printed, then the '<build-in>' stuff happens, from "gfc_cpp_init":

    cpp_change_file (cpp_in, LC_RENAME, _("<built-in>"));
    ....
  cpp_change_file (cpp_in, LC_RENAME, _("<command-line>"));

(similar: c-family/c-opts.c: c_finish_options)

This could be undone (to print 'f951') by calling cpp_change_file with to_file = NULL – but I am sure it won't have undesired side effect.


And only after the file has been successfully opened, linemap_add is called.
Thus, the '<built-in>' shows up between gfc_cpp_init() and linemap_add.

Or code wise, in gfc_init:

  if (!gfc_cpp_enabled ())
    {
      linemap_add (line_table, LC_ENTER, false, gfc_source_file, 1);
      linemap_add (line_table, LC_RENAME, false, "<built-in>", 0);
    }
  else
    gfc_cpp_init_0 ();
...
  if (gfc_cpp_enabled ())
    gfc_cpp_init ();
...
  gfc_new_file ();

with gfc_new_file:

  if (gfc_cpp_enabled ())
    {
      gfc_cpp_preprocess (gfc_source_file);
      if (!gfc_cpp_preprocess_only ())
        load_file (gfc_cpp_temporary_file (), gfc_source_file, true);
    }
  else
    load_file (gfc_source_file, NULL, true);

and in load_file:

        input = gfc_open_file (realfilename);
      
      if (input == NULL)
        gfc_fatal_error ("Cannot open file %qs", filename);
...
  f = get_file (filename, (initial && !preprocessed_p) ? LC_RENAME : LC_ENTER);

the latter then calls

  linemap_add (line_table, reason, false, f->filename, 1);

> In either case, this points to some mess in the line-map stack.

Suggestions how to improve the code above?