From 075bec57a1c63a1b1de9d95909866a6548380390 Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Fri, 5 Jun 2020 20:30:34 +0200 Subject: [PATCH] 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 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 | 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 fd88a60307ad..657d7e84c996 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -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) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index fab12b9d14f4..84bd335b9201 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -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; diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c index debdbd98ac08..3a9cce6c1514 100644 --- a/gcc/fortran/trans-common.c +++ b/gcc/fortran/trans-common.c @@ -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; -- 2.47.2