]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
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 20:22:03 +0000 (22:22 +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.

(cherry picked from commit bcd96c9cce962ca5b2c6f8459597fb759f945ccf)

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

index fd88a60307adeb815f89a88541a37998113e7a13..657d7e84c9965f53a7f302df4c61e2195fa7d315 100644 (file)
@@ -3989,7 +3989,8 @@ error_return:
 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;
@@ -4191,7 +4192,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 fab12b9d14f4e27cd4aa32b2b64e94a501fcdac9..84bd335b9201547c2c82559d86c3fc37d76894a0 100644 (file)
@@ -1652,7 +1652,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 debdbd98ac0820b927d2d4a43df4de88a25b4d1f..3a9cce6c151416d8cc721229e5a5cf7e1d987e8f 100644 (file)
@@ -1252,7 +1252,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;