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);
      | ^~~~~~~~

Reply via email to