Downstream, we had issues with some checkers, that were eval::Calling some APIs, but never bound the return value.
In such cases, no entry will be present in the Environment
, hence any expressions loading from it will end up having UnknownSVal
, poisoning computations using it. It also affects taint analysis, as taint cannot be bound to UnknownSVal
s.
To prevent such mistakes, I’d rather assert that eval::Call implementations must bind a value to the currently evaluated CallExpr
and LocationContext
by the end of the CheckerManager::runCheckersForEvalCall()
.
To register if such a bindExpr was invoked, we could check if the relevant expression and location context match the one set prior to invoking the eval::Call callbacks.
Note that, I would allow checker to explicitly bind UnknownSVal
to the CallExpr if they want to. The point is to be explicit and reliable.
Here is a quick and dirty proof-of-concept implementation for now, to kick off some discussion.
enforceEvalCallsToBindReturnValue.patch (3.9 KB)
After applying this patch, I can see 21 tests failing:
Clang :: Analysis/array-punned-region.c
Clang :: Analysis/asm.cpp
Clang :: Analysis/bsd-string.c
Clang :: Analysis/bstring.c
Clang :: Analysis/bstring_UninitRead.c
Clang :: Analysis/bug_hash_test.cpp
Clang :: Analysis/cast-value-notes.cpp
Clang :: Analysis/chroot.c
Clang :: Analysis/complex.c
Clang :: Analysis/cstring-ranges.c
Clang :: Analysis/lambdas-generalized-capture.cpp
Clang :: Analysis/lambdas.mm
Clang :: Analysis/null-deref-path-notes.c
Clang :: Analysis/null-deref-ps-region.c
Clang :: Analysis/smart-ptr-text-output.cpp
Clang :: Analysis/smart-ptr.cpp
Clang :: Analysis/std-c-library-functions-arg-cstring-dependency.c
Clang :: Analysis/string.c
Clang :: Analysis/temporaries.cpp
Clang :: Analysis/weak-functions.c
Clang :: Analysis/wstring.c
In most cases, some debug.ExprInspection
checker was declared with non-void return types triggering this assertion, so let’s ignore issues raised for that case. That way we end up with this list:
Clang :: Analysis/bsd-string.c
Clang :: Analysis/bstring.c
Clang :: Analysis/bstring_UninitRead.c
Clang :: Analysis/cast-value-notes.cpp
Clang :: Analysis/chroot.c
Clang :: Analysis/cstring-ranges.c
Clang :: Analysis/null-deref-path-notes.c
Clang :: Analysis/null-deref-ps-region.c
Clang :: Analysis/smart-ptr-text-output.cpp
Clang :: Analysis/smart-ptr.cpp
Clang :: Analysis/std-c-library-functions-arg-cstring-dependency.c
Clang :: Analysis/string.c
Clang :: Analysis/weak-functions.c
Clang :: Analysis/wstring.c
I haven’t checked this list, but for instance the Analysis/chroot.c
certainly uncovered that the ChrootChecker doesn’t bind the return value for chroot
and chdir
calls.
Do you think it would be nice to have this invariant?
@NoQ @Xazax-hun @Szelethus