But obviously not all levels of the warning can/should be enabled
with -Wall/-Werror.  There are cases which are worth warning by default
(the case where we want to inform the user if you reach this stmt,
you'll get your program killed (will call __chk_fail)) is something
that ought like before be enabled by default; can have a warning
switch users can disable.
Then there is the case where there is a sure buffer overflow (not using
-D_FORTIFY_SOURCE, but still __bos (, 0) tells the buffer is too short,
and it is unconditional (no tricks with PHIs where one path has short
and another part has long size).  This is something that is useful
in -Wall.
The rest I'm very doubtful about even for -Wextra.

I've posted an updated patch that disables the warning for the cases
you were concerned about but I want to respond these two points.

GCC issues a number of different kinds of warnings under -Wall and
-Wextra for constructs that are strictly safe but that have been
known to cause bugs down the line.  Those warnings are helpful even
if some of their instances could be considered false positives.
I think the same is even more true for warnings that help detect
defects as serious as buffer overflows.

One thing is that for useful warnings users have to be able to do something
to quiet them.  For -Wmisleading-indentation you indent your code properly,
for -Wimplicit-fallthrough you add attributes or comments, etc.
But I really don't know what you want people to do to tell the compiler
the warning is a false positive.  Add asm ("" : "+g" (ptr)); to hide
everything from the compiler?  Too ugly, too unportable, pessimizing correct
code.

That's a valid question to ask.  There are a few portable ways to
suppress these warnings.  The latest patch doesn't warn on the
examples you posted above anymore but here's one where it does
warn where  _FORTIIFY_SOURCE did not before the patch.  The example
shows the code that triggers the warning (in function f) and how
the warning can be suppressed (in function g).

The code in f is questionable (and, in my view, would be even if
it called memcpy instead) and suggests that the programmer may
have made a mistake.  If the intent is to copy the string over
the whole struct then it's better written as in g (though using
memcpy would be more appropriate).

$ cat b.c && gcc -O2 -S -Wall -Wextra b.c
extern char* strcpy (char*, const char*);

const char* const s0 = "1234";
const char* const s1 = "12345";

struct S { char a[4]; char b[4]; };

void f (struct S *s, _Bool i)
{
   strcpy (s->a, i ? s1 : s0);
}

void g (struct S *s, _Bool i)
{
   strcpy ((char*)s, i ? s1 : s0);
}

b.c: In function ‘f’:
b.c:10:3: warning: strcpy writing 5 bytes into a region of size 4 overflows the destination [-Wstringop-overflow=]
    strcpy (s->a, i ? s1 : s0);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~

Martin

Reply via email to