Bug 110878 - -Wstringop-overflow incorrectly warns about arguments to functions with static array parameter declarations
Summary: -Wstringop-overflow incorrectly warns about arguments to functions with stati...
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 13.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on: 108154
Blocks: Wstringop-overflow
  Show dependency treegraph
 
Reported: 2023-08-02 19:21 UTC by Taylor R Campbell
Modified: 2023-08-23 08:44 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Taylor R Campbell 2023-08-02 19:21:42 UTC
Isolated from code passing a pointer into an array and the length of the array as separate arguments, where each function has the minimum length of the array encoded in its parameter declaration, and uses runtime conditionals to guarantee the minimum is met:

// bar(p, n) may access p[0], p[1], ..., p[n-1], and requires n >= 128
void bar(unsigned char[static 128], unsigned);

// foo(p, n) may access p[0], p[1], ..., p[n-1], and requires n >= 16
void
foo(unsigned char p[static 16], unsigned n)
{

	if (n % 128)
		n -= n % 128;
	if (n)
		bar(p, n);
}

<source>: In function 'foo':
<source>:12:17: error: 'bar' accessing 128 bytes in a region of size 16 [-Werror=stringop-overflow=]
   12 |                 bar(p, n);
      |                 ^~~~~~~~~
<source>:12:17: note: referencing argument 1 of type 'unsigned char[128]'
<source>:2:6: note: in a call to function 'bar'
    2 | void bar(unsigned char[static 128], unsigned n);
      |      ^~~
cc1: all warnings being treated as errors
Compiler returned: 1

Reproduced in GCC 10.5, 11.4, and 12.3.  Not reproduced in any earlier versions of GCC.

Using `if (n >= 128)' doesn't change anything, presumably because GCC doesn't know the connection between p and n.
Comment 1 Andrew Pinski 2023-08-02 19:31:18 UTC
There is another bug report dealing with this. But IIRC this is an expected warning as foo is being passed an array which is size 16 but then passed to bar as size 128 which would be undefined.
Comment 2 Andrew Pinski 2023-08-02 19:36:10 UTC
This is basically a dup of bug 108154 I think.
Comment 3 Taylor R Campbell 2023-08-02 19:52:48 UTC
(In reply to Andrew Pinski from comment #1)
> There is another bug report dealing with this. But IIRC this is an expected
> warning as foo is being passed an array which is size 16 but then passed to
> bar as size 128 which would be undefined.

There is nothing undefined here.

The caller's requirement as noted in the comment (which is not formally
expressible in C, as far as I know, but is obviously extremely
widespread practice) is that for foo(p, n) or bar(p, n), p must point
to the first element of an array of at least n elements.

foo additionally imposes the requirement that p have at least 16
elements.  bar additionally imposes the requirement that p have at
least 128 elements.

When the caller meets foo's contract, foo meets bar's contract.  So
there is nothing undefined.

From C11, Sec. 6.7.6.3 `Function declarators (including prototypes)',
paragraph 7, p. 133:

> A declaration of a parameter as ``array of type'' shall be adjusted
> to ``qualified pointer to type'', where the type qualifiers (if any)
> are those specified within the [ and ] of the array type derivation.
> If the keyword static also appears within the [ and ] of the array
> type derivation, then for each call to the function, the value of the
> corresponding actual argument shall provide access to the first
> element of an array with at least as many elements as specified by
> the size expression.

Here, as required, the value of the corresponding actual argument does
provide access to the first element of an array with at least as many
elements as specified by the size expression.

In other words, this states a requirement about run-time values, which
the code meets, not about compile-time parameter declarations, which is
what GCC appears to object to.

(In reply to Andrew Pinski from comment #2)
> This is basically a dup of bug 108154 I think.

That one appears to be different: it trips -Wstringop-overread, not
-Wstringop-overflow.
Comment 4 Andrew Pinski 2023-08-02 20:00:53 UTC
(In reply to Taylor R Campbell from comment #3)
> (In reply to Andrew Pinski from comment #2)
> > This is basically a dup of bug 108154 I think.
> 
> That one appears to be different: it trips -Wstringop-overread, not
> -Wstringop-overflow.

The infrastructure for both are the same for this static array parameters though. So ....
Comment 5 Martin Uecker 2023-08-03 21:01:02 UTC
It is true that there is no UB, but the warning is not directly related to whether something is UB or not.  It simply assumes that 16 is an upper bound although the standard does require this.