[PATCH] D49057: [analyzer] Track multiple raw pointer symbols in DanglingInternalBufferChecker
Artem Dergachev via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 8 12:25:18 PDT 2018
NoQ added a comment.
Much symbols!
================
Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:126
+ NewSet = F.add(NewSet, RawPtr.getAsSymbol());
+ if (!NewSet.isEmpty()) {
+ State = State->set<RawPtrMap>(ObjRegion, NewSet);
----------------
rnkovacs wrote:
> xazax.hun wrote:
> > Is it possible here the set to be empty? We just added a new element to it above. Maybe turn this into an assert or just omit this if it is impossible?
> I'm not sure whether `add()` can fail. I turned it into an assert now and will see if it ever fails.
It totally can't. We're just adding an object to a set. What could possibly go wrong?
================
Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:32-40
+namespace clang {
+namespace ento {
+template<> struct ProgramStateTrait<PtrSet>
+ : public ProgramStatePartialTrait<PtrSet> {
+ static void *GDMIndex() {
+ static int Index = 0;
+ return &Index;
----------------
Please add a comment on how this template is useful. This trick is used by some checkers, but it's a veeeery unobvious trick. We should probably add a macro for that, i.e. `REGISTER_FACTORY_WITH_PROGRAMSTATE` or something like that.
================
Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:113
- const SymbolRef *StrBufferPtr = State->get<RawPtrMap>(TypedR);
- // FIXME: What if Origin is null?
const Expr *Origin = Call.getOriginExpr();
----------------
Maybe turn the FIXME into a NOTE or something like that. It indeed seems fine, but let's still make sure the reader realizes that there's a subtle potential problem here.
================
Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:115
SVal RawPtr = Call.getReturnValue();
if (!RawPtr.isUnknown()) {
+ // Start tracking this raw pointer by adding it to the set of symbols
----------------
I'd much rather unwrap the symbol here, i.e. `if (SymbolRef Sym = RawPtr.getAsSymbol())`. A lot of other cornercases may occur if the implementation is accidentally inlined (`Undefined`, concrete regions). Also, speculatively, `.getAsSymbol(/* search for symbolic base = */ true)` for the same reason//*//.
If we didn't care about inlined implementations, the `Unknown` check would have been redundant. So it should also be safe to straightforwardly ignore inlined implementations by consulting `C.wasInlined`, then the presence of the symbol can be asserted. But i'd rather speculatively care about inlined implementations as long as it seems easy.
__
//*// In fact your code relies on a very wonky implementation detail of our `SVal` hierarchy: namely, pointer-type return values of conservatively evaluated functions are always expressed as `&SymRegion{conj_$N<pointer type>}` and never as `&element{SymRegion{conj_$N<pointer type>}, 0 S32b, pointee type}`. Currently nobody knows the rules under which zero element regions are added in different parts of the analyzer, i.e. what is the "canonical" representation of the symbolic pointer, though i made a few attempts to speculate.
================
Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:119
+ PtrSet::Factory &F = State->getStateManager().get_context<PtrSet>();
+ PtrSet NewSet = F.getEmptySet();
+ if (const PtrSet *OldSet = State->get<RawPtrMap>(ObjRegion)) {
----------------
My favorite idiom for such cases, looks a bit cleaner:
```
const PtrSet *SetPtr = State->get<RawPtrMap>(ObjRegion)
PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet()
```
================
Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:122
+ NewSet = *OldSet;
+ if (NewSet.contains(RawPtr.getAsSymbol()))
+ return;
----------------
This `contains` check is very unlikely to yield true because if the implementation is not inlined, the symbol is newly born. I'd much rather skip the check; it doesn't sound like it'd make things any faster.
Even better, let's assert that: `assert(C.wasInlined || !Set.contains(Sym))`. It'll probably help us catch some "reincarnated symbol" bugs in the core.
https://reviews.llvm.org/D49057
More information about the cfe-commits
mailing list