[gcc(refs/vendors/ARM/heads/arm-perf-staging)] PR fortran/95530, PR fortran/95537 - Buffer overflows with long symbols

Tamar Christina tnfchris@gcc.gnu.org
Fri Jul 17 15:22:21 GMT 2020


https://gcc.gnu.org/g:36442ee216acbe9a345ae625be53efbde8626477

commit 36442ee216acbe9a345ae625be53efbde8626477
Author: Harald Anlauf <anlauf@gmx.de>
Date:   Fri Jun 5 20:30:34 2020 +0200

    PR fortran/95530, PR fortran/95537 - Buffer overflows with long symbols
    
    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.
    
    (cherry picked from commit bcd96c9cce962ca5b2c6f8459597fb759f945ccf)

Diff:
---
 gcc/fortran/decl.c         | 9 +++++++--
 gcc/fortran/gfortran.h     | 3 ++-
 gcc/fortran/trans-common.c | 6 +++++-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 9cc81361f43..bcc850e9130 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -4079,7 +4079,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;
@@ -4269,7 +4270,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)
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 5af44847f9b..0ef7b1b0eff 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -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;
diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c
index bf163bc4f52..24d842d4da7 100644
--- a/gcc/fortran/trans-common.c
+++ b/gcc/fortran/trans-common.c
@@ -1313,7 +1313,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;


More information about the Gcc-cvs mailing list