Re: BPF selftests and strict aliasing

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

 



> 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.)

>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
     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