[PATCH] D122150: [clang][analyzer] Add checker for bad use of 'errno'.
Artem Dergachev via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 22 10:48:21 PDT 2022
NoQ added inline comments.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp:47-49
+ mutable bool ErrnoInitialized = false;
+ mutable Optional<Loc> ErrnoLoc;
+ mutable const MemRegion *ErrnoRegion = nullptr;
----------------
steakhal wrote:
> One should not define member variables like this.
> The analysis engine might explore exploded nodes in an unpredictable order, invoking the checker's handler callbacks in an indeterminate order.
> You should have registered simple value traits for this purpose, associating the necessary information with a given State.
In this case it's probably fine given that the variable doesn't really change throughout a single ExplodedGraph construction. But I agree that it doesn't really make sense to cache this data; `getErrnoLoc()` an O(1) lookup anyway.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp:68-71
+ if (ErrnoLoc) {
+ ErrnoRegion = ErrnoLoc->getAsRegion();
+ assert(ErrnoRegion && "The 'errno' location should be a memory region.");
+ }
----------------
steakhal wrote:
> `Loc` always wrap a memregion of some sort.
Nope; null pointer is a `Loc` but doesn't correspond to any memory region.
I usually print out doxygen inheritance graphs:
- https://clang.llvm.org/doxygen/classclang_1_1ento_1_1SVal__inherit__graph.png
- https://clang.llvm.org/doxygen/classclang_1_1ento_1_1SymExpr__inherit__graph.png
- https://clang.llvm.org/doxygen/classclang_1_1ento_1_1MemRegion__inherit__graph.png
and hang them on the wall near my desk. They're really handy.
On a separate note, why not make this assertion part of `getErrnoLoc()`?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp:93
+ OS << CallD->getIdentifier()->getName();
+ OS << "' might overwrite value of 'errno'";
+ PathDiagnosticLocation Loc{
----------------
"May" is more neutral.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp:97
+ C.getSourceManager()};
+ BR->addNote(OS.str(), Loc, {CallMayChangeErrno->getSourceRange()});
+ }
----------------
This path-insensitive note is attached to the exact same source location as the warning, right? I think this should be part of the warning instead. Something like this:
```lang=c
foo(); // (1) path note: Call to 'foo()' indicates failure only by setting 'errno'
bar(); // (2) warning: Value of 'errno' potentially overwritten by 'bar()' was not checked
```
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp:104
+void ErrnoChecker::checkBeginFunction(CheckerContext &C) const {
+ // The errno location must be refreshed at every new function.
+ ErrnoInitialized = false;
----------------
Note that `checkBeginFunction()` is every time a nested stack frame is entered. This happens much more often than an update to the variable is needed.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D122150/new/
https://reviews.llvm.org/D122150
More information about the cfe-commits
mailing list