Re: BPF selftests and strict aliasing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 1/29/24 10:43 AM, Jose E. Marchesi wrote:
On 1/29/24 9:05 AM, Jose E. Marchesi wrote:
On Sun, 2024-01-28 at 21:33 -0800, Yonghong Song wrote:
[...]
I tried below example with the above prog/dynptr_fail.c case with gcc 11.4
for native x86 target and didn't trigger the warning. Maybe this requires
latest gcc? Or test C file is not sufficient enough to trigger the warning?

[~/tmp1]$ cat t.c
struct t {
     char a;
     short b;
     int c;
};
void init(struct t *);
long foo() {
     struct t dummy;
     init(&dummy);
     return *(int *)&dummy;
}
[~/tmp1]$ gcc -Wall -Werror -O2 -g -Wno-compare-distinct-pointer-types -c t.c
[~/tmp1]$ gcc --version
gcc (GCC) 11.4.1 20230605 (Red Hat 11.4.1-2)
I managed to trigger this warning for gcc 13.2.1:

      $ gcc -fstrict-aliasing -Wstrict-aliasing=1 -c test-punning.c -o /dev/null
      test-punning.c: In function ‘foo’:
      test-punning.c:10:19: warning: dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]
         10 |    return *(int *)&dummy;
            |                   ^~~~~~
      Note the -Wstrict-aliasing=1 option, w/o =1 suffix it does not
trigger.

Grepping words "strict-aliasing", "strictaliasing", "strict_aliasing"
through clang code-base does not show any diagnostic related tests or
detection logic. It appears to me clang does not warn about strict
aliasing violations at all and -Wstrict-aliasing=* are just stubs at
the moment.
Detecting strict aliasing violations can only be done by looking at
particular code constructions (casts immediately followed by
dereferencing for example) so GCC provides these three levels: 1, 2, and
3 which is the default.  Level 1 can result in false positives (hence
the "might" in the warning message) while higher levels have less false
positives, but will likely miss lots of real positives.
clang has not implemented this yet.

In this case, it seems to me clear that a pointer to int does not alias
a pointer to struct t.  So I would say, in this little program
strict-aliasing=1 catches a real positive, while strict-aliasing=3
misses a real positive.
This make sense. But could you pose the exact bpf compilation command
line which triggers strict-aliasing warning? Does the compiler command
line have -fstrict-aliasing?
In GCC -fstrict-aliasing is activated at levels -O2, -O3 and -Os.  From
a quick look at Clang.cpp, I _think_ it generally assumes strict
aliasing when optimizing except when it tries to be compatible with
Visual Studio C++ compilers (that clang-cl driver thingie.)

I double checked again. You are right, -fno-strict-aliasing does work
to disable strict-aliasing. Looks like clang also has -fstrict-alaising
as the default if optimization level is not O0. But somehow, clang
did not issue warnings...


 From the GCC manual:

'-fstrict-aliasing'
      Allow the compiler to assume the strictest aliasing rules
      applicable to the language being compiled.  For C (and C++), this
      activates optimizations based on the type of expressions.  In
      particular, an object of one type is assumed never to reside at the
      same address as an object of a different type, unless the types are
      almost the same.  For example, an 'unsigned int' can alias an
      'int', but not a 'void*' or a 'double'.  A character type may alias
      any other type.

      Pay special attention to code like this:
           union a_union {
             int i;
             double d;
           };

           int f() {
             union a_union t;
             t.d = 3.0;
             return t.i;
           }
      The practice of reading from a different union member than the one
      most recently written to (called "type-punning") is common.  Even
      with '-fstrict-aliasing', type-punning is allowed, provided the
      memory is accessed through the union type.  So, the code above
      works as expected.  *Note Structures unions enumerations and
      bit-fields implementation::.  However, this code might not:
           int f() {
             union a_union t;
             int* ip;
             t.d = 3.0;
             ip = &t.i;
             return *ip;
           }

      Similarly, access by taking the address, casting the resulting
      pointer and dereferencing the result has undefined behavior, even

This is an alarm since enabling -fstrict-aliasing may produce
undefined behavior if the code is written in a strange way which
violates some casting rules. So -fno-strict-aliasing is the
right solution to address this potential undefined behavior.
We probably should not recommend -fno-strict-aliasing sicne it
may hurt performance and production bpf programs should be
more type friendly.

So I think your option (b) sounds good. Thanks!

      if the cast uses a union type, e.g.:
           int f() {
             double d = 3.0;
             return ((union a_union *) &d)->i;
           }

      The '-fstrict-aliasing' option is enabled at levels '-O2', '-O3',
      '-Os'.




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux