[PATCH] D122150: [clang][analyzer] Add checker for bad use of 'errno'.
Balázs Benics via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 16 06:30:22 PDT 2022
steakhal added a comment.
It looks great.
Let me check the test coverage and the generated docs page it everything looks great.
================
Comment at: clang/docs/analyzer/checkers.rst:2538
+may change value of ``errno`` if the call does not fail.
+Therefore ``errno`` should only be used if it is known from the return value
+of a function that the call has failed.
----------------
================
Comment at: clang/docs/analyzer/checkers.rst:2540
+of a function that the call has failed.
+There are exceptions to this rule but the affected functions are not
+yet supported by the checker.
----------------
Please mention at least one of those functions.
================
Comment at: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td:553-554
+ CheckerOptions<[
+ CmdLineOption<Boolean,
+ "AllowErrnoReadOutsideConditionExpressions",
+ "Allow read of undefined value from errno outside of conditions",
----------------
Well, now I see why you marked this `Hide` previously.
This is a //modeling// checker, thus it won't appear in the documentation nor in the `-analyzer-checker-help` etc.
Interestingly, other checkers mark some options `Hide` and other times `DontHide`.
E.g. `DynamicMemoryModeling.Optimistic` is //displayed//, but the `DynamicMemoryModeling.AddNoOwnershipChangeNotes` is //hidden//.
Whatever.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp:145
+
+ if (IsLoad) {
+ switch (EState) {
----------------
Might be more readable to early return instead.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp:205
+ if (CallF->isExternC() && CallF->isGlobal() &&
+ C.getSourceManager().isInSystemHeader(CallF->getLocation()) &&
+ !isErrno(CallF)) {
----------------
Does this refer to the callsite or to the Decl location?
I think the former, which would be a bug I think.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoChecker.cpp:46
+
+ /// Indicates if a read (load) of 'errno' is allowed in a non-conditional
+ /// statement.
----------------
martong wrote:
> Or `in a statement without a condition` ?
I don't really understand this comment. What is a //non-condition part of a statement//?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp:280
+ BR.markNotInteresting(ErrnoR);
+ return Message.c_str();
+ }
----------------
balazske wrote:
> steakhal wrote:
> >
> I can not omit `c_str`, there is a compile error probably related to lambda return type.
Yes, you will need to specify explicitly the return type of the lambda: `-> std::string`.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp:267-268
+ if (const auto *VD = dyn_cast_or_null<VarDecl>(D))
+ return VD->getIdentifier() &&
+ VD->getIdentifier()->getName() == ErrnoVarName;
+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
----------------
balazske wrote:
> steakhal wrote:
> > It looks odd that in the very next `if` block you have `II` and here you don't.
> I do not get what you mean here.
I was thinking about this:
```lang=C++
bool isErrno(const Decl *D) {
if (const auto *VD = dyn_cast_or_null<VarDecl>(D))
if (const IdentifierInfo *II = VD->getIdentifier())
return II->getName() == ErrnoVarName;
if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
if (const IdentifierInfo *II = FD->getIdentifier())
return llvm::is_contained(ErrnoLocationFuncNames, II->getName());
return false;
}
```
This way both checks would follow the same pattern, symmetry.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h:34
+ /// value.
+ Errno_MustNotBeChecked = 2
+};
----------------
balazske wrote:
> steakhal wrote:
> > You don't need to prefix these with `Errno_`. It's already contained by a specific namespace.
> > https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly
> > > Unless the enumerators are defined in their own small namespace or inside a class, enumerators should have a prefix corresponding to the enum declaration name
> Without `Errno_` these sound too generic. Probably have only `Errno` prefix, not `Errno_`?
But you always refer to it by it's qualified name: `errno_modeling::Errno_Irrelevant`.
In which case this prefix is just noise IMO. That's what I'm about.
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