From b342cfd648e6658363c7c8fef83af8f59dba1795 Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Sun, 7 Jun 2020 14:47:24 +0200 Subject: [PATCH] PR fortran/95091 - Buffer overflows with submodules and long symbols With submodules, name mangling results in long internal symbols. This requires adjustment of the sizes of temporaries to avoid buffer overflows. 2020-06-07 Harald Anlauf gcc/fortran/ PR fortran/95091 * class.c (get_unique_type_string, gfc_hash_value): Enlarge buffers, and check whether the strings returned by get_unique_type_string() fit. --- gcc/fortran/class.c | 13 ++++++++----- gcc/testsuite/gfortran.dg/pr95091.f90 | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/pr95091.f90 diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c index b176407..8bb7350 100644 --- a/gcc/fortran/class.c +++ b/gcc/fortran/class.c @@ -509,9 +509,11 @@ get_unique_type_string (char *string, gfc_symbol *derived) static void get_unique_hashed_string (char *string, gfc_symbol *derived) { - /* Provide sufficient space to hold "symbol_Pdtsymbol". */ - char tmp[2*GFC_MAX_SYMBOL_LEN+5]; + /* Provide sufficient space to hold "symbol.symbol_symbol". */ + char tmp[3*GFC_MAX_SYMBOL_LEN+3]; get_unique_type_string (&tmp[0], derived); + size_t len = strnlen (tmp, sizeof (tmp)); + gcc_assert (len < sizeof (tmp)); /* If string is too long, use hash value in hex representation (allow for extra decoration, cf. gfc_build_class_symbol & gfc_find_derived_vtab). We need space to for 15 characters "__class_" + symbol name + "_%d_%da", @@ -532,12 +534,13 @@ unsigned int gfc_hash_value (gfc_symbol *sym) { unsigned int hash = 0; - /* Provide sufficient space to hold "symbol_Pdtsymbol". */ - char c[2*GFC_MAX_SYMBOL_LEN+5]; + /* Provide sufficient space to hold "symbol.symbol_symbol". */ + char c[3*GFC_MAX_SYMBOL_LEN+3]; int i, len; get_unique_type_string (&c[0], sym); - len = strlen (c); + len = strnlen (c, sizeof (c)); + gcc_assert (len < sizeof (c)); for (i = 0; i < len; i++) hash = (hash << 6) + (hash << 16) - hash + c[i]; diff --git a/gcc/testsuite/gfortran.dg/pr95091.f90 b/gcc/testsuite/gfortran.dg/pr95091.f90 new file mode 100644 index 0000000..1c48dca --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr95091.f90 @@ -0,0 +1,19 @@ +! { dg-do compile } +! { dg-options "-fsecond-underscore" } +! PR fortran/95091 - ICE in gfc_hash_value + +module m2345678901234567890123456789012345678901234567890123456789_123 + type t2345678901234567890123456789012345678901234567890123456789_123 + end type t2345678901234567890123456789012345678901234567890123456789_123 + interface + module subroutine s2345678901234567890123456789012345678901234567890123456789_123 & + (x2345678901234567890123456789012345678901234567890123456789_123) + end + end interface +end +submodule(m2345678901234567890123456789012345678901234567890123456789_123) & + n2345678901234567890123456789012345678901234567890123456789_123 + type, extends(t2345678901234567890123456789012345678901234567890123456789_123) :: & + u2345678901234567890123456789012345678901234567890123456789_123 + end type +end -- 2.7.4