https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77293

            Bug ID: 77293
           Summary: __builtin_object_size inconsistent for
                    multidimensional arrays
           Product: gcc
           Version: 7.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: ---

While testing a patch for bug 71831 (as per
https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01363.html) I noticed some
inconsistencies in how __builtin_object_size handles multidimensional arrays. 
The test case below shows that the built-in returns a different result
depending on whether or not the offset in the expression is a constant.  In
particular, in type 1, when it is a constant the built-in evaluates to 1 while
when it is not a constant it evaluates to 4 in this case.  The manual suggests
that 4 should be expected: "If the least significant bit is clear, objects are
whole variables, if it is set, a closest surrounding subobject is considered
the object a pointer points to."

I don't need a fix for what I'm doing but it seems to me that the (type & 1)
functionality has been a source of confusion (see also bug 44384) and would be
best either deprecated or documented as less than fully reliable.  (The
documentation itself is ambiguous: what is "a closest surrounding subobject" of
an element of a multidimensional array?  Is it the higher-ranked subarray, the
entire array object, or, when the array object is a member of a structure, is
it the structure object?

$ (set -x && cat xyz.c && for N in a 1; do /build/gcc-trunk-svn/gcc/xgcc -B
/build/gcc-trunk-svn/gcc -DN=$N -O2 xyz.c && ./a.out; done)
+ cat xyz.c
static char x2x3[2][3];

#define strcpy(d, s) \
  __builtin___strcpy_chk (d, s, __builtin_object_size (d, 1))

int main (void)
{
  int a = 1;

  strcpy (&x2x3[0][1] + N, "abc"); 
}

+ for N in a 1
+ /build/gcc-trunk-svn/gcc/xgcc -B /build/gcc-trunk-svn/gcc -DN=a -O2 xyz.c
+ ./a.out
+ for N in a 1
+ /build/gcc-trunk-svn/gcc/xgcc -B /build/gcc-trunk-svn/gcc -DN=1 -O2 xyz.c
xyz.c: In function ‘main’:
xyz.c:4:3: warning: call to __builtin___memcpy_chk will always overflow
destination buffer
   __builtin___strcpy_chk (d, s, __builtin_object_size (d, 1))
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xyz.c:10:3: note: in expansion of macro ‘strcpy’
   strcpy (&x2x3[0][1] + N, "abc");
   ^~~~~~
+ ./a.out
*** buffer overflow detected ***: ./a.out terminated
======= Backtrace: =========
/lib64/libc.so.6(+0x77d9e)[0x7f983241dd9e]
/lib64/libc.so.6(__fortify_fail+0x37)[0x7f98324b7db7]
...

Reply via email to