> > > This breaks bootstrap:
> > > 
> > > https://gcc.gnu.org/pipermail/gcc-regression/2020-May/072642.html
> > > 
> > > ../../src-master/gcc/fortran/class.c:487:13: error: ‘char*
> > > strncpy(char*, const char*, size_t)’ specified bound 67 equals
> > > destination size [-Werror=stringop-truncation]
> > >   487 |     strncpy (dt_name, gfc_dt_upper_string (derived->name),
> > > sizeof (dt_name));
> > 
> > So should one use the clumsy way:
> > 
> >            strncpy(buf, str, buflen - 1);
> >            if (buflen > 0)
> >                buf[buflen - 1]= '\0';
> > 
> > Or is there something more convenient that keeps gcc happy?
> 
> Depends on what exactly you want to achieve, but strncpy is pretty much
> always the wrong answer.
> Do you really want to clear the rest of buf, when gfc_dt_upper_string
> is much shorter?  That is one thing that is only seldom useful from strncpy
> behavior.  The other is that it doesn't zero terminate on truncation.
> I'd suggest e.g. remember gfc_dt_upper_string result in a temporary,
> compute len = strnlen (res, sizeof (dt_name) - 1);
> and then you can just memcpy and zero terminate buf[len] = '\0';
> Or do you ever want to truncate?

I'ld like to detect the situation that when somebody modifies name-mangling in
a way that generates a buffer overrun during regtesting so that the temporaries
to adjust are easier to find.

After thinking about your and H.J.'s suggestions, the shortest solution
I came up with is:

diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index db395624a16..6d0924da2b8 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -484,7 +484,12 @@ get_unique_type_string (char *string, gfc_symbol *derived)
   if (derived->attr.unlimited_polymorphic)
     strcpy (dt_name, "STAR");
   else
-    strncpy (dt_name, gfc_dt_upper_string (derived->name), sizeof (dt_name));
+    {
+      dt_name[sizeof (dt_name)-1] = '\0';
+      strcpy (dt_name, gfc_dt_upper_string (derived->name));
+      if (dt_name[sizeof (dt_name)-1] != '\0')
+       gfc_internal_error ("get_unique_type_string: identifier overflow");
+    }
   if (derived->attr.unlimited_polymorphic)
     sprintf (string, "_%s", dt_name);
   else if (derived->module)

That would have given me a useful error on x86_64.

Is this OK for master?

Harald

Reply via email to