diff options
author | Harald Anlauf <anlauf@gmx.de> | 2020-06-20 16:11:48 +0200 |
---|---|---|
committer | Harald Anlauf <anlauf@gmx.de> | 2020-06-20 16:11:48 +0200 |
commit | ac932bfcd21e9523fa2b880ae8138aef79da7f54 (patch) | |
tree | 86f87ceec028505517b4ae6b621a4e89aba71fdb /gcc/fortran/class.c | |
parent | 62c0c0ea7bfb6f8f6b8d767b05120cafb6823da6 (diff) | |
download | gcc-ac932bfcd21e9523fa2b880ae8138aef79da7f54.zip gcc-ac932bfcd21e9523fa2b880ae8138aef79da7f54.tar.gz gcc-ac932bfcd21e9523fa2b880ae8138aef79da7f54.tar.bz2 |
PR fortran/95687 - ICE in get_unique_hashed_string, at fortran/class.c:508
With submodules and PDTs, name mangling of interfaces may result in long
internal symbols overflowing a previously static internal buffer. We now
set the buffer size dynamically.
gcc/fortran/
PR fortran/95687
* class.c (get_unique_type_string): Return a string with dynamic
length.
(get_unique_hashed_string, gfc_hash_value): Use dynamic result
from get_unique_type_string instead of static buffer.
Diffstat (limited to 'gcc/fortran/class.c')
-rw-r--r-- | gcc/fortran/class.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c index 227134e..2b760ef 100644 --- a/gcc/fortran/class.c +++ b/gcc/fortran/class.c @@ -476,22 +476,38 @@ gfc_class_initializer (gfc_typespec *ts, gfc_expr *init_expr) and module name. This is used to construct unique names for the class containers and vtab symbols. */ -static void -get_unique_type_string (char *string, gfc_symbol *derived) +static char * +get_unique_type_string (gfc_symbol *derived) { const char *dt_name; + char *string; + size_t len; if (derived->attr.unlimited_polymorphic) dt_name = "STAR"; else dt_name = gfc_dt_upper_string (derived->name); + len = strlen (dt_name) + 2; if (derived->attr.unlimited_polymorphic) - sprintf (string, "_%s", dt_name); + { + string = XNEWVEC (char, len); + sprintf (string, "_%s", dt_name); + } else if (derived->module) - sprintf (string, "%s_%s", derived->module, dt_name); + { + string = XNEWVEC (char, strlen (derived->module) + len); + sprintf (string, "%s_%s", derived->module, dt_name); + } else if (derived->ns->proc_name) - sprintf (string, "%s_%s", derived->ns->proc_name->name, dt_name); + { + string = XNEWVEC (char, strlen (derived->ns->proc_name->name) + len); + sprintf (string, "%s_%s", derived->ns->proc_name->name, dt_name); + } else - sprintf (string, "_%s", dt_name); + { + string = XNEWVEC (char, len); + sprintf (string, "_%s", dt_name); + } + return string; } @@ -502,10 +518,8 @@ static void get_unique_hashed_string (char *string, gfc_symbol *derived) { /* 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)); + char *tmp; + tmp = get_unique_type_string (derived); /* 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", @@ -517,6 +531,7 @@ get_unique_hashed_string (char *string, gfc_symbol *derived) } else strcpy (string, tmp); + free (tmp); } @@ -527,16 +542,16 @@ gfc_hash_value (gfc_symbol *sym) { unsigned int hash = 0; /* Provide sufficient space to hold "symbol.symbol_symbol". */ - char c[3*GFC_MAX_SYMBOL_LEN+3]; + char *c; int i, len; - get_unique_type_string (&c[0], sym); - len = strnlen (c, sizeof (c)); - gcc_assert ((size_t) len < sizeof (c)); + c = get_unique_type_string (sym); + len = strlen (c); for (i = 0; i < len; i++) hash = (hash << 6) + (hash << 16) - hash + c[i]; + free (c); /* Return the hash but take the modulus for the sake of module read, even though this slightly increases the chance of collision. */ return (hash % 100000000); |