The new attribute can be placed on statements in order to suppress
arbitrary warnings produced by static analysis tools at those statements.
Previously such suppressions were implemented as either informal comments
(eg. clang-tidy `// NOLINT:`) or with preprocessor macros (eg.
clang static analyzer's `#ifdef __clang_analyzer__`). The attribute
provides a universal, formal, flexible and neat-looking suppression mechanism.
Implement support for the new attribute in the clang static analyzer;
clang-tidy coming soon.
The attribute allows specifying which specific warnings to suppress,
in the form of free-form strings that are intended to be specific to
the tools, but currently none are actually supported; so this is also
going to be a future improvement.
Differential Revision: https://reviews.llvm.org/D93110
When merging commit c873f77e87a9ebd02f94d6b9d46e84d43e1ceb38 I didn't
manually rebase it onto the tip of the main branch, so I didn't notice
that the testcase that's added by it needs to be tweaked to account for
the effects of commit 2f29ded4f98e8e1fa26725c618a08082a09b405a (which
was also merged by me a few days ago).
The checker EnumCastOutOfRange verifies the (helpful, but not
standard-mandated) design rule that integer to enum casts should not
produce values that don't have a corresponding enumerator. As it was
improved and cleaned up by recent changes, this commit renames it from
`alpha.cplusplus.EnumCastOutOfRange` to `optin.core.EnumCastOutOfRange`
to reflect that it's no longer alpha quality.
As this checker handles a basic language feature (which is also present
in plain C), I moved it to a "core" subpackage within "optin".
In addition to the renaming, this commit cleans up the documentation in
`checkers.rst` and adds the new example code to a test file to ensure
that it's indeed producing the behavior claimend in the documentation.
...that is causing the bug report when it's converted to the enum type.
This commit only improves the diagnostics and does not affect the set of
reports.
...instead of the currently used, more abstract Location callback. The
main advantage of this change is that after it the checker will check
`array[index].field` while the previous implementation ignored this
situation (because here the ElementRegion is wrapped in a FieldRegion
object). This improvement fixes PR #70187.
Note that after this change `&array[idx]` will be handled as an access
to the `idx`th element of `array`, which is technically incorrect but
matches the programmer intuitions. In my opinion it's more helpful if
the report points to the source location where the indexing happens
(instead of the location where a pointer is finally dereferenced).
As a special case, this change allows code that forms the past-the-end
pointer of an array as `&arr[size]` (but still rejects code like
`if (idx >= size) return &array[idx];` and code that dereferences a
past-the-end pointer).
In addition to this primary improvement, this change tweaks the message
for the tainted index/offset case (using the more concrete information
that's available now) and clarifies/improves a few testcases.
The main change of this commit (replacing `check::Location` with
`check::PostStmt<...>` callbacks) was already proposed in my change
https://reviews.llvm.org/D150446 and https://reviews.llvm.org/D159107 by
steakhal. Those reviews were both abandoned, but the problems that led
to abandonment were unrelated to the change that is introduced in this
PR.
This commit extends the class `SValBuilder` with the methods
`getMinValue()` and `getMaxValue()` to that work like
`SValBuilder::getKnownValue()` but return the minimal/maximal possible
value the `SVal` is not perfectly constrained.
This extension of the ConstraintManager API is discussed at:
https://discourse.llvm.org/t/expose-the-inferred-range-information-in-warning-messages/75192
As a simple proof-of-concept application of this new API, this commit
extends a message from `core.BitwiseShift` with some range information
that reports the assumptions of the analyzer.
My main motivation for adding these methods is that I'll also want to
use them in `ArrayBoundCheckerV2` to make the error messages less
awkward, but I'm starting with this simpler and less important usecase
because I want to avoid merge conflicts with my other commit
https://github.com/llvm/llvm-project/pull/72107 which is currently under
review.
The testcase `too_large_right_operand_compound()` shows a situation
where querying the range information does not work (and the extra
information is not added to the error message). This also affects the
debug utility `clang_analyzer_value()`, so the problem isn't in the
fresh code. I'll do some investigations to resolve this, but I think
that this commit is a step forward even with this limitation.
...to model the results of alloca() and _alloca() calls. Previously it
acted as if these functions were returning memory from the heap, which
led to alpha.security.ArrayBoundV2 producing incorrect messages.
Thanks to recent improvements in #67663, InvalidPtr checker does not
emit any false positives on the following OS projects: memcached, tmux,
curl, twin, vim, openssl, sqlite, ffmpeg, postgres, tinyxml2, libwebm,
xerces, bitcoin, protobuf, qtbase, contour, acid, openrct2. (Before the
changes mentioned above, there were 27 reports, catching the `getenv`
invalidates previous `getenv` results cases. That strict behaviour is
disabled by default)
As my BSc thesis I've implemented a checker for std::variant and
std::any, and in the following weeks I'll upload a revised version of
them here.
# Prelude
@Szelethus and I sent out an email with our initial plans here:
https://discourse.llvm.org/t/analyzer-new-checker-for-std-any-as-a-bsc-thesis/65613/2
We also created a stub checker patch here:
https://reviews.llvm.org/D142354.
Upon the recommendation of @haoNoQ , we explored an option where instead
of writing a checker, we tried to improve on how the analyzer natively
inlined the methods of std::variant and std::any. Our attempt is in this
patch https://reviews.llvm.org/D145069, but in a nutshell, this is what
happened: The analyzer was able to model much of what happened inside
those classes, but our false positive suppression machinery erroneously
suppressed it. After months of trying, we could not find a satisfying
enhancement on the heuristic without introducing an allowlist/denylist
of which functions to not suppress.
As a result (and partly on the encouragement of @Xazax-hun) I wrote a
dedicated checker!
The advantage of the checker is that it is not dependent on the
standard's implementation and won't put warnings in the standard library
definitions. Also without the checker it would be difficult to create
nice user-friendly warnings and NoteTags -- as per the standard's
specification, the analysis is sinked by an exception, which we don't
model well now.
# Design ideas
The working of the checker is straightforward: We find the creation of
an std::variant instance, store the type of the variable we want to
store in it, then save this type for the instance. When retrieving type
from the instance we check what type we want to retrieve as, and compare
it to the actual type. If the two don't march we emit an error.
Distinguishing variants by instance (e.g. MemRegion *) is not the most
optimal way. Other checkers, like MallocChecker uses a symbol-to-trait
map instead of region-to-trait. The upside of using symbols (which would
be the value of a variant, not the variant itself itself) is that the
analyzer would take care of modeling copies, moves, invalidation, etc,
out of the box. The problem is that for compound types, the analyzer
doesn't create a symbol as a result of a constructor call that is fit
for this job. MallocChecker in contrast manipulates simple pointers.
My colleges and I considered the option of making adjustments directly
to the memory model of the analyzer, but for the time being decided
against it, and go with the bit more cumbersome, but immediately viable
option of simply using MemRegions.
# Current state and review plan
This patch contains an already working checker that can find and report
certain variant/any misuses, but still lands it in alpha. I plan to
upload the rest of the checker in later patches.
The full checker is also able to "follow" the symbolic value held by the
std::variant and updates the program state whenever we assign the value
stored in the variant. I have also built a library that is meant to
model union-like types similar to variant, hence some functions being a
bit more multipurpose then is immediately needed.
I also intend to publish my std::any checker in a later commit.
---------
Co-authored-by: Gabor Spaits <gabor.spaits@ericsson.com>
Co-authored-by: Balazs Benics <benicsbalazs@gmail.com>
The checker now displays one combined note tag for errno-related and
"case"-related notes. Previous functions in the errno-modeling part that
were used for construction of note tags are removed. The note tag added
by StdLibraryFunctionsChecker contains the code to display the note tag
for 'errno' (this was done previously by these removed functions).
This is a hacky fix to get the bots green, because just reverting the
original commit causes more failures. This should be replaced with a
proper fix by the author.
This reverts commit 8ee07a4be7f7d8654ecf25e7ce0a680975649544.
The revert is breaking AMDGPU backend tests (which I didn't have
enabled), and I don't want to risk breakages over the weekend, so just
revert for now.
This reverts commit 3bb7ecc5a515d2ddd2708257096e14e3fe3b839d.
The revert breaks AMDGPU backend tests (which I didn't have enabled
locally), and I don't want to risk more breakages before the weekend, so
just restore things as they were.
This reverts commit cd7ba9f3d090afb5d3b15b0dcf379d15d1e11e33.
This is causing test failures on builds without assertions:
/data/users/smeenai/llvm-project/clang/test/Analysis/builtin_signbit.cpp:14:21: error: CHECK-BE32-NEXT: expected string not found in input
// CHECK-BE32-NEXT: entry:
^
Bots are also failing, e.g. https://lab.llvm.org/buildbot/#/builders/67/builds/13266/steps/7/logs/stdio
This reverts commit 82f68a992b9f89036042d57a5f6345cb2925b2c1.
cd7ba9f3d090afb5d3b15b0dcf379d15d1e11e33 needs to be reverted to fix
test failures on builds without assertions, and this one needs to be
reverted first for that.
Previously alpha.security.ArrayBoundV2 produced very spartan bug
reports; this commit ensures that the relevant (and known) details are
reported to the user.
The logic for detecting bugs is not changed, after this commit the
checker will report the same set of issues, but with better messages.
To test the details of the message generation this commit adds a new
test file 'out-of-bounds-diagnostics.c'. Three of the testcases are
added with FIXME notes because they reveal shortcomings of the existing
modeling and bounds checking code. I will try to fix them in separate
follow-up commits.
Workaround the case when the `this` pointer is actually a `NonLoc`, by
returning `Unknown` instead.
The solution isn't ideal, as `this` should be really a `Loc`, but due to
how casts work, I feel this is our easiest and best option.
As this patch presents, I'm evaluating a cast to transform the `NonLoc`.
However, given that `evalCast()` can't be cast from `NonLoc` to a
pointer type thingy (`Loc`), we end up with `Unknown`.
It is because `EvalCastVisitor::VisitNonLocSymbolVal()` only evaluates
casts that happen from NonLoc to NonLocs.
When I tried to actually implement that case, I figured:
1) Create a `SymbolicRegion` from that `nonloc::SymbolVal`; but
`SymbolRegion` ctor expects a pointer type for the symbol.
2) Okay, just have a `SymbolCast`, getting us the pointer type; but
`SymbolRegion` expects `SymbolData` symbols, not generic `SymExpr`s, as
stated:
> // Because pointer arithmetic is represented by ElementRegion layers,
> // the base symbol here should not contain any arithmetic.
3) We can't use `ElementRegion`s to perform this cast because to have an
`ElementRegion`, you already have to have a `SubRegion` that you want to
cast, but the point is that we don't have that.
At this point, I gave up, and just left a FIXME instead, while still
returning `Unknown` on that path.
IMO this is still better than having a crash.
Fixes#69922
Fixes#70464
When ctor is not declared in the base class, initializing the base class
with the initializer list will not trigger a proper assignment of the
base region, as a CXXConstructExpr doing that is not available in the
AST.
This patch checks whether the init expr is an InitListExpr under a base
initializer, and adds a binding if so.
EnumCastOutOfRange checker now reports the name of the enum in the
warning message. Additionally, a note-tag is placed to highlight the
location of the declaration.
Static analyze can't report diagnose when statement after a
CXXForRangeStmt and enable widen, because
`ExprEngine::processCFGBlockEntrance` lacks of CXXForRangeStmt and when
`AMgr.options.maxBlockVisitOnPath - 1` equals to `blockCount`, it can't
widen. After next iteration, `BlockCount >=
AMgr.options.maxBlockVisitOnPath` holds and generate a sink node. Add
`CXXForRangeStmt` makes it work.
Co-authored-by: huqizhi <836744285@qq.com>
Introduce 'InvalidatingGetEnv' checker option for 'getenv' calls.
- POSIX suggests consecutive 'getenv' calls may invalidate
pointer pointers. This is often too strict in real-world scenarios.
- New 'InvalidatingGetEnv' checker option provides a more
pragmatic default that doesn't treat consecutive 'getenv'
calls as invalidating.
- Now also handles main function specifications with an
environment pointer as the third parameter.
Original Phabricator review:
https://reviews.llvm.org/D154603
Reapplication of 7339c0f782d5c70e0928f8991b0c05338a90c84c with a fix
for a crash involving arrays without a size expression.
Clang supports VLAs in C++ as an extension, but we currently only warn
on their use when you pass -Wvla, -Wvla-extension, or -pedantic.
However, VLAs as they're expressed in C have been considered by WG21
and rejected, are easy to use accidentally to the surprise of users
(e.g., https://ddanilov.me/default-non-standard-features/), and they
have potential security implications beyond constant-size arrays
(https://wiki.sei.cmu.edu/confluence/display/c/ARR32-C.+Ensure+size+arguments+for+variable+length+arrays+are+in+a+valid+range).
C++ users should strongly consider using other functionality such as
std::vector instead.
This seems like sufficiently compelling evidence to warn users about
VLA use by default in C++ modes. This patch enables the -Wvla-extension
diagnostic group in C++ language modes by default, and adds the warning
group to -Wall in GNU++ language modes. The warning is still opt-in in
C language modes, where support for VLAs is somewhat less surprising to
users.
RFC: https://discourse.llvm.org/t/rfc-diagnosing-use-of-vlas-in-c/73109
Fixes https://github.com/llvm/llvm-project/issues/62836
Differential Revision: https://reviews.llvm.org/D156565
In the following code:
```cpp
int main() {
struct Wrapper {char c; int &ref; };
Wrapper w = {.c = 'a', .ref = *(int *)0 };
w.ref = 1;
}
```
The clang static analyzer will produce the following warnings and notes:
```
test.cpp:12:11: warning: Dereference of null pointer [core.NullDereference]
12 | w.ref = 1;
| ~~~~~~^~~
test.cpp:11:5: note: 'w' initialized here
11 | Wrapper w = {.c = 'a', .ref = *(int *)0 };
| ^~~~~~~~~
test.cpp:12:11: note: Dereference of null pointer
12 | w.ref = 1;
| ~~~~~~^~~
1 warning generated.
```
In the line where `w` is created, the note gives information about the
initialization of `w` instead of `w.ref`. Let's compare it to a similar
case where a null pointer dereference happens to a pointer member:
```cpp
int main() {
struct Wrapper {char c; int *ptr; };
Wrapper w = {.c = 'a', .ptr = nullptr };
*w.ptr = 1;
}
```
Here the following error and notes are seen:
```
test.cpp:18:12: warning: Dereference of null pointer (loaded from field 'ptr') [core.NullDereference]
18 | *w.ptr = 1;
| ~~~ ^
test.cpp:17:5: note: 'w.ptr' initialized to a null pointer value
17 | Wrapper w = {.c = 'a', .ptr = nullptr };
| ^~~~~~~~~
test.cpp:18:12: note: Dereference of null pointer (loaded from field 'ptr')
18 | *w.ptr = 1;
| ~~~ ^
1 warning generated.
```
Here the note that shows the initialization the initialization of
`w.ptr` in shown instead of `w`.
This commit is here to achieve similar notes for member reference as the
notes of member pointers, so the report looks like the following:
```
test.cpp:12:11: warning: Dereference of null pointer [core.NullDereference]
12 | w.ref = 1;
| ~~~~~~^~~
test.cpp:11:5: note: 'w.ref' initialized to a null pointer value
11 | Wrapper w = {.c = 'a', .ref = *(int *)0 };
| ^~~~~~~~~
test.cpp:12:11: note: Dereference of null pointer
12 | w.ref = 1;
| ~~~~~~^~~
1 warning generated.
```
Here the initialization of `w.ref` is shown instead of `w`.
---------
Authored-by: Gábor Spaits <gabor.spaits@ericsson.com>
Reviewed-by: Donát Nagy <donat.nagy@ericsson.com>
This checker reports cases where an array of polymorphic objects are
deleted as their base class. Deleting an array where the array's static
type is different from its dynamic type is undefined.
Since the checker is similar to DeleteWithNonVirtualDtorChecker, I
refactored that checker to support more detection types.
This checker corresponds to the SEI Cert rule EXP51-CPP: Do not delete
an array through a pointer of the incorrect type.
Differential Revision: https://reviews.llvm.org/D158156
```
@interface A : NSObject
@property (nonnull, nonatomic, strong) NSString *name;
+ (nullable instancetype)shared;
@end
@[[A shared].name];
```
Consider the code above, the nullability of the name property should
depend on the result of the shared method. A warning is expected because
of adding a nullable object to array.
ObjCMessageExpr gets the actual type through
Sema::getMessageSendResultType, instead of using the return type of
MethodDecl directly. The final type is generated by considering the
nullability of receiver and MethodDecl together.
Thus, the RetType in NullabilityChecker should all be replaced with
M.getOriginExpr()->getType().
Co-authored-by: tripleCC <triplecc@gmail.com>
This change avoids a crash in BasicValueFactory by checking the bit
width of an APSInt to avoid calling getZExtValue if greater than
64-bits. This was caught by our internal, randomized test generator.
Clang invocation
clang -cc1 -analyzer-checker=optin.portability.UnixAPI case.c
<src-root>/llvm/include/llvm/ADT/APInt.h:1488:
uint64_t llvm::APInt::getZExtValue() const: Assertion `getActiveBits()
<= 64
&& "Too many bits for uint64_t"' failed.
...
#9 <address> llvm::APInt::getZExtValue() const
<src-root>/llvm/include/llvm/ADT/APInt.h:1488:5
clang::BinaryOperatorKind, llvm::APSInt const&, llvm::APSInt const&)
<src-root>/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp:307:37
llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>,
clang::BinaryOperatorKind, clang::ento::NonLoc, clang::ento::NonLoc,
clang::QualType)
<src-root>/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp:531:31
llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>,
clang::BinaryOperatorKind, clang::ento::SVal, clang::ento::SVal,
clang::QualType)
<src-root>/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp:532:26
...
Previously, bitwise shifts with constant operands were validated by the
checker `core.UndefinedBinaryOperatorResult`. However, this logic was
unreliable, and commit 25b9696b61e53a958e217bb3d0eab66350dc187f added
the dedicated checker `core.BitwiseShift` which validated the
preconditions of all bitwise shifts with a more accurate logic (that
uses the real types from the AST instead of the unreliable type
information encoded in `APSInt` objects).
This commit disables the inaccurate logic that could mark bitwise shifts
as 'undefined' and removes the redundant shift-related warning messages
from core.UndefinedBinaryOperatorResult. The tests that were validating
this logic are also deleted by this commit; but I verified that those
testcases trigger the expected bug reports from `core.BitwiseShift`. (I
didn't convert them to tests of `core.BitwiseShift`, because that
checker already has its own extensive test suite with many analogous
testcases.)
I hope that there will be a time when the constant folding will be
reliable, but until then we need hacky solutions like this improve the
quality of results.