[llvm-bugs] [Bug 46941] New: Opaque constructor confuses static analyzer

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Jul 31 12:35:41 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=46941

            Bug ID: 46941
           Summary: Opaque constructor confuses static analyzer
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Static Analyzer
          Assignee: dcoughlin at apple.com
          Reporter: nicolas.alvarez at gmail.com
                CC: dcoughlin at apple.com, llvm-bugs at lists.llvm.org

I was making a custom static-analyzer checker, and I hit an issue that I then
managed to reproduce with built-in checkers too:

#include <stdio.h>

class QString { public: QString(); };

class Obj {
public:
    Obj();
    ~Obj();

private:
    FILE *f;
#if BREAK_IT
    QString m_title;
#endif
};

Obj::Obj():
    f(fopen("file.txt","w"))
{
    ;
}
Obj::~Obj()
{
    fclose(f);
}

void foo() {
    Obj w;
}


Running the alpha.unix.Stream checker on this code warns on the fclose call
that the stream pointer might be NULL (since the fopen return value wasn't
checked). However, the warning goes away if I define BREAK_IT=1, ie. if the
QString member is present right after the FILE*.

The key to this is that the QString constructor is opaque (its definition isn't
visible in this translation unit). Adding an empty {} body to the QString
constructor makes the stream warning appear normally. So does calling fopen
inside the Obj constructor body instead of the initializer list, or moving the
QString member *before* the FILE* member (both changes make the QString
construction happen before the fopen). It's as if the static analyzer thought
that the QString constructor might modify f, but I don't see how that's
possible.

I modified StreamChecker::ensureStreamNonNull to print out the SVal for the
stream. If the QString isn't present (-DBREAK_IT=0), I get this:
StreamVal: &SymRegion{conj_$0{FILE *, LC2, S11791, #1}}
test.cpp:24:5: warning: Stream pointer might be NULL [alpha.unix.Stream]

If the QString is present (-DBREAK_IT=1), I get this:
StreamVal: &SymRegion{derived_$5{conj_$1{int, LC2, S11974, #1},w.f}}

This is very similar to what I was seeing with my own checker. In my checker,
in the BREAK_IT=0 case I get a SymbolRef that looks like "conj_$1{class
QNetworkAccessManager *, LC2, S1571, #1}" when printed out, and getting its
state with ctx.getState()->get<MyCheckerMap>(symbol) returns the same custom
state I added with state->set(); while in the BREAK_IT=1 case I get
"derived_$10{conj_$6{int, LC2, S1862, #1},w.m_networkAccessManager}", and
get<MyCheckerMap>(symbol) returns null.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200731/ac29f91d/attachment.html>


More information about the llvm-bugs mailing list