For details, see PR. If I have not miscounted, the failing message has 32 characters + three names → (3*62 + 1 + 32) = 219 > 200. I add another 18 characters for longer translation strings. If that is not enough, there will be truncation but no buffer overflow thanks to snprintf.
OK for mainline and GCC 10? [If there are no comments or an OK, I intent to commit it as obvious tomorrow.] Tobias PS: Patches which I would like to see in GCC 11 and 10, but which are still pending review: * [Patch] Fortran: Fix intrinsic null() handling [PR99651] * [Patch] Fortran: Fix func decl mismatch [PR93660] ----------------- Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank Thürauf
Fortran: Extend buffer, use snprintf to avoid overflows [PR99369] gcc/fortran/ChangeLog: PR fortran/99369 * resolve.c (resolve_operator): Make 'msg' buffer larger and use snprintf. gcc/testsuite/ChangeLog: PR fortran/99369 * gfortran.dg/longnames.f90: New test. gcc/fortran/resolve.c | 82 ++++++++++++++++------------- gcc/testsuite/gfortran.dg/longnames.f90 | 92 +++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 37 deletions(-) diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 715fecd4b3a..1c9b0c5cb62 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -3994,7 +3994,8 @@ static bool resolve_operator (gfc_expr *e) { gfc_expr *op1, *op2; - char msg[200]; + /* One error uses 3 names; additional space for wording (also via gettext). */ + char msg[3*GFC_MAX_SYMBOL_LEN + 1 + 50]; bool dual_locus_error; bool t = true; @@ -4047,7 +4048,8 @@ resolve_operator (gfc_expr *e) if ((op1 && op1->expr_type == EXPR_NULL) || (op2 && op2->expr_type == EXPR_NULL)) { - sprintf (msg, _("Invalid context for NULL() pointer at %%L")); + snprintf (msg, sizeof (msg), + _("Invalid context for NULL() pointer at %%L")); goto bad_op; } @@ -4063,8 +4065,9 @@ resolve_operator (gfc_expr *e) break; } - sprintf (msg, _("Operand of unary numeric operator %%<%s%%> at %%L is %s"), - gfc_op2string (e->value.op.op), gfc_typename (e)); + snprintf (msg, sizeof (msg), + _("Operand of unary numeric operator %%<%s%%> at %%L is %s"), + gfc_op2string (e->value.op.op), gfc_typename (e)); goto bad_op; case INTRINSIC_PLUS: @@ -4079,14 +4082,14 @@ resolve_operator (gfc_expr *e) } if (op1->ts.type == BT_DERIVED || op2->ts.type == BT_DERIVED) - sprintf (msg, - _("Unexpected derived-type entities in binary intrinsic " - "numeric operator %%<%s%%> at %%L"), + snprintf (msg, sizeof (msg), + _("Unexpected derived-type entities in binary intrinsic " + "numeric operator %%<%s%%> at %%L"), gfc_op2string (e->value.op.op)); else - sprintf (msg, - _("Operands of binary numeric operator %%<%s%%> at %%L are %s/%s"), - gfc_op2string (e->value.op.op), gfc_typename (op1), + snprintf (msg, sizeof(msg), + _("Operands of binary numeric operator %%<%s%%> at %%L are %s/%s"), + gfc_op2string (e->value.op.op), gfc_typename (op1), gfc_typename (op2)); goto bad_op; @@ -4099,9 +4102,9 @@ resolve_operator (gfc_expr *e) break; } - sprintf (msg, - _("Operands of string concatenation operator at %%L are %s/%s"), - gfc_typename (op1), gfc_typename (op2)); + snprintf (msg, sizeof (msg), + _("Operands of string concatenation operator at %%L are %s/%s"), + gfc_typename (op1), gfc_typename (op2)); goto bad_op; case INTRINSIC_AND: @@ -4142,9 +4145,10 @@ resolve_operator (gfc_expr *e) goto simplify_op; } - sprintf (msg, _("Operands of logical operator %%<%s%%> at %%L are %s/%s"), - gfc_op2string (e->value.op.op), gfc_typename (op1), - gfc_typename (op2)); + snprintf (msg, sizeof (msg), + _("Operands of logical operator %%<%s%%> at %%L are %s/%s"), + gfc_op2string (e->value.op.op), gfc_typename (op1), + gfc_typename (op2)); goto bad_op; @@ -4165,8 +4169,8 @@ resolve_operator (gfc_expr *e) break; } - sprintf (msg, _("Operand of .not. operator at %%L is %s"), - gfc_typename (op1)); + snprintf (msg, sizeof (msg), _("Operand of .not. operator at %%L is %s"), + gfc_typename (op1)); goto bad_op; case INTRINSIC_GT: @@ -4276,16 +4280,16 @@ resolve_operator (gfc_expr *e) } if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL) - sprintf (msg, - _("Logicals at %%L must be compared with %s instead of %s"), - (e->value.op.op == INTRINSIC_EQ - || e->value.op.op == INTRINSIC_EQ_OS) - ? ".eqv." : ".neqv.", gfc_op2string (e->value.op.op)); + snprintf (msg, sizeof (msg), + _("Logicals at %%L must be compared with %s instead of %s"), + (e->value.op.op == INTRINSIC_EQ + || e->value.op.op == INTRINSIC_EQ_OS) + ? ".eqv." : ".neqv.", gfc_op2string (e->value.op.op)); else - sprintf (msg, - _("Operands of comparison operator %%<%s%%> at %%L are %s/%s"), - gfc_op2string (e->value.op.op), gfc_typename (op1), - gfc_typename (op2)); + snprintf (msg, sizeof (msg), + _("Operands of comparison operator %%<%s%%> at %%L are %s/%s"), + gfc_op2string (e->value.op.op), gfc_typename (op1), + gfc_typename (op2)); goto bad_op; @@ -4296,19 +4300,23 @@ resolve_operator (gfc_expr *e) const char *guessed; guessed = lookup_uop_fuzzy (name, e->value.op.uop->ns->uop_root); if (guessed) - sprintf (msg, _("Unknown operator %%<%s%%> at %%L; did you mean '%s'?"), - name, guessed); + snprintf (msg, sizeof (msg), + _("Unknown operator %%<%s%%> at %%L; did you mean '%s'?"), + name, guessed); else - sprintf (msg, _("Unknown operator %%<%s%%> at %%L"), name); + snprintf (msg, sizeof (msg), _("Unknown operator %%<%s%%> at %%L"), + name); } else if (op2 == NULL) - sprintf (msg, _("Operand of user operator %%<%s%%> at %%L is %s"), - e->value.op.uop->name, gfc_typename (op1)); + snprintf (msg, sizeof (msg), + _("Operand of user operator %%<%s%%> at %%L is %s"), + e->value.op.uop->name, gfc_typename (op1)); else { - sprintf (msg, _("Operands of user operator %%<%s%%> at %%L are %s/%s"), - e->value.op.uop->name, gfc_typename (op1), - gfc_typename (op2)); + snprintf (msg, sizeof (msg), + _("Operands of user operator %%<%s%%> at %%L are %s/%s"), + e->value.op.uop->name, gfc_typename (op1), + gfc_typename (op2)); e->value.op.uop->op->sym->attr.referenced = 1; } @@ -4391,8 +4399,8 @@ resolve_operator (gfc_expr *e) /* Try user-defined operators, and otherwise throw an error. */ dual_locus_error = true; - sprintf (msg, - _("Inconsistent ranks for operator at %%L and %%L")); + snprintf (msg, sizeof (msg), + _("Inconsistent ranks for operator at %%L and %%L")); goto bad_op; } } diff --git a/gcc/testsuite/gfortran.dg/longnames.f90 b/gcc/testsuite/gfortran.dg/longnames.f90 new file mode 100644 index 00000000000..046179ea2fb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/longnames.f90 @@ -0,0 +1,92 @@ +! { dg-do compile } +! +! PR fortran/99369 +! +! Contributed by G. Steinmetz +! + +module m1bcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc + type tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc + end type + interface operator (.oabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc.) + procedure fabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc + end interface +contains + function fabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc & + (uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc) + type (tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc), intent(in) :: & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc + end +end +subroutine p1 + use m1bcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc + type (tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc) :: & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc + wabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc = & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc & + .oabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc. & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabc +end + + +module m2bcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd + type tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd + end type + interface operator (.oabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd.) + procedure fabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd + end interface +contains + function fabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd & + (uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd) + type (tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd), intent(in) :: & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd + end +end +subroutine p2 + use m2bcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd + type (tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd) :: & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd + wabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd = & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd & + .oabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd. & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcd +end + + +module m3bcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab + type tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab + end type + interface operator (.oabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab.) + procedure fabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab + end interface +contains + function fabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab & + (uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab) + type (tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab), intent(in) :: & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab + end +end +subroutine p3 + use m3bcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab + type (tabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab) :: & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab, & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab + wabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab = & + uabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab & + .oabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab. & + vabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzabcdefgxyzab +end + +program main + call p1 + call p2 + call p3 +end