https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96508
Bug ID: 96508
Summary: missing warning for invalid calls to builtins from
inline functions defined in system headers
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: msebor at gcc dot gnu.org
Target Milestone: ---
Prompted by the discussion at
https://gcc.gnu.org/pipermail/gcc-patches/2020-August/551526.html, the test
case below shows that warnings aren't issued for invalid calls to built-in
functions like memcpy called from inline functions defined in system headers
unless those inline functions are also declared artificial.
Since the artificial attribute is used only rarely (there are only two
instances of it in all of libstdc++), this limitation defeats most
out-of-bounds checking in such wrappers.
$ gcc -O2 -S -Wall -Wextra x.c
#ifndef SYSTEM_HEADER_H
#define SYSTEM_HEADER_H
#pragma GCC system_header
__attribute__ ((access (write_only, 1, 3))) void
sys_func (void*, const void*, int);
__attribute__ ((access (write_only, 1, 3), artificial)) static inline void
sys_func_artificial_inline (void *d, const void *s, int n)
{
__builtin_memcpy (d, s, n);
}
__attribute__ ((access (write_only, 1, 3))) static inline void
sys_func_inline (void *d, const void *s, int n)
{
__builtin_memcpy (d, s, n);
}
#endif // SYSTEM_HEADER_H
#include "system-header.h"
__attribute__ ((access (write_only, 1, 3))) static inline void
func_inline (void *d, const void *s, int n)
{
sys_func (d, s, n);
}
void* f1 (const void *s)
{
void *d = __builtin_malloc (3);
sys_func (d, s, 5); // warning (good)
return d;
}
void* f2 (const void *s)
{
void *d = __builtin_malloc (3);
sys_func_artificial_inline (d, s, 6); // warning (good)
return d;
}
void* f3 (const void *s)
{
void *d = __builtin_malloc (3);
sys_func_inline (d, s, 7); // missing warning!
return d;
}
void* f4 (const void *s)
{
void *d = __builtin_malloc (3);
func_inline (d, s, 8); // warning (good)
return d;
}
x.c: In function ‘f1’:
x.c:12:3: warning: ‘sys_func’ writing 5 bytes into a region of size 3 overflows
the destination [-Wstringop-overflow=]
12 | sys_func (d, s, 5); // warning (good)
| ^~~~~~~~~~~~~~~~~~
In file included from x.c:1:
system-header.h:7:1: note: in a call to function ‘sys_func’ declared with
attribute ‘write_only (1, 3)’
7 | sys_func (void*, const void*, int);
| ^~~~~~~~
In function ‘sys_func_artificial_inline’,
inlined from ‘f2’ at x.c:19:3:
system-header.h:12:3: warning: ‘__builtin_memcpy’ writing 6 bytes into a region
of size 3 [-Wstringop-overflow=]
12 | __builtin_memcpy (d, s, n);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
x.c: In function ‘f2’:
x.c:18:13: note: at offset 0 to an object with size 3 allocated by
‘__builtin_malloc’ here
18 | void *d = __builtin_malloc (3);
| ^~~~~~~~~~~~~~~~~~~~
In function ‘func_inline’,
inlined from ‘f4’ at x.c:33:3:
x.c:6:3: warning: ‘sys_func’ writing 8 bytes into a region of size 3 overflows
the destination [-Wstringop-overflow=]
6 | sys_func (d, s, n);
| ^~~~~~~~~~~~~~~~~~
In file included from x.c:1:
x.c: In function ‘f4’:
system-header.h:7:1: note: in a call to function ‘sys_func’ declared with
attribute ‘write_only (1, 3)’
7 | sys_func (void*, const void*, int);
| ^~~~~~~~