PR fortran/95530, PR fortran/95537 - Buffer overflows with long symbols
authorHarald Anlauf <anlauf@gmx.de>
Fri, 5 Jun 2020 18:30:34 +0000 (20:30 +0200)
committerHarald Anlauf <anlauf@gmx.de>
Fri, 5 Jun 2020 18:30:34 +0000 (20:30 +0200)
The testcases for PR95090 and PR95106 trigger buffer overflows with long
symbols that were found with an instrumented compiler.  Enlarge the
affected buffers, and add checks that the buffers will suffice.

2020-06-05  Harald Anlauf  <anlauf@gmx.de>

gcc/fortran/
PR fortran/95530
PR fortran/95537
* decl.c (gfc_match_decl_type_spec): Enlarge buffer, and enhance
string copy to detect buffer overflow.
* gfortran.h (gfc_common_head): Enlarge buffer.
* trans-common.c (finish_equivalences): Enhance string copy to
detect buffer overflow.

gcc/fortran/decl.c
gcc/fortran/gfortran.h
gcc/fortran/trans-common.c

index 3ad5559c3ecb8057f81a18ad5bb23850f7cdbc2e..1c1626d3fa45670184bfbf3ad000e2bec0ae3e3f 100644 (file)
@@ -4094,7 +4094,8 @@ match_byte_typespec (gfc_typespec *ts)
 match
 gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
 {
-  char name[GFC_MAX_SYMBOL_LEN + 1];
+  /* Provide sufficient space to hold "pdtsymbol".  */
+  char name[GFC_MAX_SYMBOL_LEN + 1 + 3];
   gfc_symbol *sym, *dt_sym;
   match m;
   char c;
@@ -4284,7 +4285,11 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
            return m;
          gcc_assert (!sym->attr.pdt_template && sym->attr.pdt_type);
          ts->u.derived = sym;
-         strcpy (name, gfc_dt_lower_string (sym->name));
+         const char* lower = gfc_dt_lower_string (sym->name);
+         size_t len = strnlen (lower, sizeof (name));
+         gcc_assert (len < sizeof (name));
+         memcpy (name, lower, len);
+         name[len] = '\0';
        }
 
       if (sym && sym->attr.flavor == FL_STRUCT)
index 5af44847f9b0152dc67437278933f3177f8115cb..0ef7b1b0effb182d156eacda29eeeca5f8ced040 100644 (file)
@@ -1677,7 +1677,8 @@ typedef struct gfc_common_head
   char use_assoc, saved, threadprivate;
   unsigned char omp_declare_target : 1;
   unsigned char omp_declare_target_link : 1;
-  char name[GFC_MAX_SYMBOL_LEN + 1];
+  /* Provide sufficient space to hold "symbol.eq.1234567890".  */
+  char name[GFC_MAX_SYMBOL_LEN + 1 + 14];
   struct gfc_symbol *head;
   const char* binding_label;
   int is_bind_c;
index 3775a8bea747ee3ac62d2b71a0a3ea939bd6c7d8..1acc336eacfef415e62584abe7326c67afa06ddc 100644 (file)
@@ -1314,7 +1314,11 @@ finish_equivalences (gfc_namespace *ns)
              c->where = ns->proc_name->declared_at;
            else if (ns->is_block_data)
              c->where = ns->sym_root->n.sym->declared_at;
-           strcpy (c->name, z->module);
+
+           size_t len = strlen (z->module);
+           gcc_assert (len < sizeof (c->name));
+           memcpy (c->name, z->module, len);
+           c->name[len] = '\0';
          }
        else
          c = NULL;