Skip to content

Commit df58018

Browse files
author
einvbri
committed
[analyzer] Get direct binding for specific punned case
Region store was not able to see through this case to the actual initialized value of STRUCT ff. This change addresses this case by getting the direct binding. This was found and debugged in a downstream compiler, with debug guidance from @steakhal. A positive and negative test case is added. The specific case where this issue was exposed. typedef struct { int a:1; int b[2]; } STRUCT; int main() { STRUCT ff = {0}; STRUCT* pff = &ff; int a = ((int)pff + 1); return a; } Reviewed By: steakhal, martong Differential Revision: https://reviews.llvm.org/D124349
1 parent 3497a4f commit df58018

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

clang/lib/StaticAnalyzer/Core/RegionStore.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2147,8 +2147,13 @@ RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
21472147
return UnknownVal();
21482148

21492149
// Additionally allow introspection of a block's internal layout.
2150-
if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion()))
2150+
// Try to get direct binding if all other attempts failed thus far.
2151+
// Else, return UndefinedVal()
2152+
if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion())) {
2153+
if (const Optional<SVal> &V = B.getDefaultBinding(R))
2154+
return *V;
21512155
return UndefinedVal();
2156+
}
21522157
}
21532158

21542159
// All other values are symbolic.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false -triple x86_64-pc-linux-gnu %s
2+
3+
// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false -triple i386-pc-linux-gnu %s
4+
5+
int clang_analyzer_eval(int);
6+
7+
typedef struct {
8+
int a : 1;
9+
int b[2];
10+
} BITFIELD_CAST;
11+
12+
void array_struct_bitfield_1() {
13+
BITFIELD_CAST ff = {0};
14+
BITFIELD_CAST *pff = &ff;
15+
clang_analyzer_eval(*((int *)pff + 1) == 0); // expected-warning{{TRUE}}
16+
ff.b[0] = 3;
17+
clang_analyzer_eval(*((int *)pff + 1) == 3); // expected-warning{{TRUE}}
18+
}
19+
20+
int array_struct_bitfield_2() {
21+
BITFIELD_CAST ff = {0};
22+
BITFIELD_CAST *pff = &ff;
23+
int a = *((int *)pff + 2); // expected-warning{{Assigned value is garbage or undefined [core.uninitialized.Assign]}}
24+
return a;
25+
}
26+
27+
typedef struct {
28+
unsigned int a : 1;
29+
unsigned int x : 31;
30+
unsigned int c : 1;
31+
int b[2];
32+
} mystruct;
33+
34+
void array_struct_bitfield_3() {
35+
mystruct ff;
36+
mystruct *pff = &ff;
37+
ff.b[0] = 3;
38+
clang_analyzer_eval(*((int *)pff + 2) == 3); // expected-warning{{TRUE}}
39+
}

0 commit comments

Comments
 (0)