mirror of https://github.com/microsoft/clang.git
[analyzer] Fix false negative on post-increment of uninitialized variable.
Summary: Currently clang static analyzer does warn on: ``` int x; x+=1; x-=1; x=x+1; x=x-1; ``` But does warn on: ``` int x; x++; x--; --x; ++x; ``` This differential should fix that. Fixes https://bugs.llvm.org/show_bug.cgi?id=35419 Reviewers: dcoughlin, NoQ Reviewed By: dcoughlin Subscribers: NoQ, xazax.hun, szepet, cfe-commits, a.sidorin Tags: #clang Differential Revision: https://reviews.llvm.org/D40463 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@319411 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e7af182053
commit
d9b383bb5c
|
@ -257,6 +257,9 @@ libclang
|
|||
Static Analyzer
|
||||
---------------
|
||||
|
||||
- Static Analyzer can now properly detect and diagnose unary pre-/post-
|
||||
increment/decrement on an uninitialized value.
|
||||
|
||||
...
|
||||
|
||||
Undefined Behavior Sanitizer (UBSan)
|
||||
|
|
|
@ -60,6 +60,14 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
|
|||
const Expr *ex = nullptr;
|
||||
|
||||
while (StoreE) {
|
||||
if (const UnaryOperator *U = dyn_cast<UnaryOperator>(StoreE)) {
|
||||
str = "The expression is an uninitialized value. "
|
||||
"The computed value will also be garbage";
|
||||
|
||||
ex = U->getSubExpr();
|
||||
break;
|
||||
}
|
||||
|
||||
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
|
||||
if (B->isCompoundAssignmentOp()) {
|
||||
ProgramStateRef state = C.getState();
|
||||
|
|
|
@ -1043,7 +1043,14 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
|
|||
|
||||
// Propagate unknown and undefined values.
|
||||
if (V2_untested.isUnknownOrUndef()) {
|
||||
Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V2_untested));
|
||||
state = state->BindExpr(U, LCtx, V2_untested);
|
||||
|
||||
// Perform the store, so that the uninitialized value detection happens.
|
||||
Bldr.takeNodes(*I);
|
||||
ExplodedNodeSet Dst3;
|
||||
evalStore(Dst3, U, U, *I, state, loc, V2_untested);
|
||||
Bldr.addNodes(Dst3);
|
||||
|
||||
continue;
|
||||
}
|
||||
DefinedSVal V2 = V2_untested.castAs<DefinedSVal>();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -128,7 +128,7 @@ int collectionIsNotEmptyNSArray(NSArray *A) {
|
|||
int count = [A count];
|
||||
if (count > 0) {
|
||||
int i;
|
||||
int j;
|
||||
int j = 0;
|
||||
for (NSString *a in A) {
|
||||
i = 1;
|
||||
j++;
|
||||
|
@ -141,7 +141,7 @@ int collectionIsNotEmptyNSArray(NSArray *A) {
|
|||
void onlySuppressExitAfterZeroIterations(NSMutableDictionary *D) {
|
||||
if (D.count > 0) {
|
||||
int *x;
|
||||
int i;
|
||||
int i = 0;
|
||||
for (NSString *key in D) {
|
||||
x = 0;
|
||||
i++;
|
||||
|
@ -155,7 +155,7 @@ void onlySuppressExitAfterZeroIterations(NSMutableDictionary *D) {
|
|||
void onlySuppressLoopExitAfterZeroIterations_WithContinue(NSMutableDictionary *D) {
|
||||
if (D.count > 0) {
|
||||
int *x;
|
||||
int i;
|
||||
int i = 0;
|
||||
for (NSString *key in D) {
|
||||
x = 0;
|
||||
i++;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc,core,alpha.core.CallAndMessageUnInitRefArg -analyzer-output=text -verify %s
|
||||
// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc,core,alpha.core.CallAndMessageUnInitRefArg,debug.ExprInspection -analyzer-output=text -verify %s
|
||||
|
||||
void clang_analyzer_warnIfReached();
|
||||
|
||||
// Passing uninitialized const data to function
|
||||
#include "Inputs/system-header-simulator.h"
|
||||
|
@ -121,6 +123,32 @@ void f_12(void) {
|
|||
|
||||
}
|
||||
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=35419
|
||||
void f11_0(void) {
|
||||
int x; // expected-note {{'x' declared without an initial value}}
|
||||
x++; // expected-warning {{The expression is an uninitialized value. The computed value will also be garbage}}
|
||||
// expected-note@-1 {{The expression is an uninitialized value. The computed value will also be garbage}}
|
||||
clang_analyzer_warnIfReached(); // no-warning
|
||||
}
|
||||
void f11_1(void) {
|
||||
int x; // expected-note {{'x' declared without an initial value}}
|
||||
++x; // expected-warning {{The expression is an uninitialized value. The computed value will also be garbage}}
|
||||
// expected-note@-1 {{The expression is an uninitialized value. The computed value will also be garbage}}
|
||||
clang_analyzer_warnIfReached(); // no-warning
|
||||
}
|
||||
void f11_2(void) {
|
||||
int x; // expected-note {{'x' declared without an initial value}}
|
||||
x--; // expected-warning {{The expression is an uninitialized value. The computed value will also be garbage}}
|
||||
// expected-note@-1 {{The expression is an uninitialized value. The computed value will also be garbage}}
|
||||
clang_analyzer_warnIfReached(); // no-warning
|
||||
}
|
||||
void f11_3(void) {
|
||||
int x; // expected-note {{'x' declared without an initial value}}
|
||||
--x; // expected-warning {{The expression is an uninitialized value. The computed value will also be garbage}}
|
||||
// expected-note@-1 {{The expression is an uninitialized value. The computed value will also be garbage}}
|
||||
clang_analyzer_warnIfReached(); // no-warning
|
||||
}
|
||||
|
||||
int f_malloc_1(void) {
|
||||
int *ptr;
|
||||
|
||||
|
|
Loading…
Reference in New Issue