Geoffrey1014 / SA_Bugs

record bugs of static analyzers
1 stars 1 forks source link

[clang static analyzer] `clang_analyzer_eval` result error for `((&b) + 1) < ((&b) + 2)` #45

Closed 0-0x41 closed 1 year ago

0-0x41 commented 1 year ago

date: 2023-1-14 commit: 0c0681b7414c385d0fd5fad302c0d48607262050 args: --analyze -Xclang -analyzer-stats -Xclang -analyzer-checker=core,debug.ExprInspection test:

#include <stdbool.h>
void clang_analyzer_eval();

struct a b;
struct a {};

void main()
{
    if (&b == &b)
    {
        clang_analyzer_eval(((&b) + 1) < ((&b) + 2));
        if (((&b) + 1) < ((&b) + 2))
        {
            *(int *)0;
        }
    }
}

report: https://github.com/llvm/llvm-project/issues/60161 fix: original:

0-0x41 commented 1 year ago

Compiling and running this case through clang(trunk) shows that ((&b) + 1) < ((&b) + 2) results in FALSE, while analyzer gives TRUE. Based on the TRUE result, it appears that analyzer does not enter the if branch for analysis (and does not generate a core.NullDereference warning for *(int *)0). See it live: https://godbolt.org/z/axdEdMzf8.

Geoffrey1014 commented 1 year ago

((&b) + 1) < ((&b) + 2) is UB. I have changed it to the following one. CSA does a good job. See it live: https://godbolt.org/z/EzqKKzGnM

#include <stdbool.h>
#include <stdio.h>

void clang_analyzer_eval();

struct a b;
struct a {int t;};

int main()
{
    struct a * p = &b;
    int * q =0;
    if (p == p)
    {
        clang_analyzer_eval(((&b) + 0) < ((&b) + 1));
        if ((p + 0) < (p + 1))
        {
            *q = 111;
            printf("hello\n");
        }
    }
}