vabridgers created this revision. vabridgers added reviewers: NoQ, steakhal. Herald added subscribers: manas, ASDenysPetrov, martong, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun. Herald added a project: All. vabridgers requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
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; } Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D124349 Files: clang/lib/StaticAnalyzer/Core/RegionStore.cpp clang/test/Analysis/array-struct-region.c Index: clang/test/Analysis/array-struct-region.c =================================================================== --- clang/test/Analysis/array-struct-region.c +++ clang/test/Analysis/array-struct-region.c @@ -353,3 +353,21 @@ // FIXME: Should be TRUE. clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{UNKNOWN}} } + +typedef struct { + int a:1; + int b[2]; +} BITFIELD_CAST; + +int array_struct_bitfield_1() { + BITFIELD_CAST ff = {0}; + BITFIELD_CAST* pff = &ff; + return *((int*)pff + 1); +} + +int array_struct_bitfield_2() { + BITFIELD_CAST ff = {0}; + BITFIELD_CAST* pff = &ff; + int a = *((int*)pff + 2); // expected-warning{{Assigned value is garbage or undefined [core.uninitialized.Assign]}} + return a; +} Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2153,8 +2153,13 @@ return UnknownVal(); // Additionally allow introspection of a block's internal layout. - if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion())) + // Try to get direct binding if all other attempts failed thus far. + // Else, return UndefinedVal() + if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion())) { + if (const Optional<SVal> &V = B.getDefaultBinding(R)) + return *V; return UndefinedVal(); + } } // All other values are symbolic.
Index: clang/test/Analysis/array-struct-region.c =================================================================== --- clang/test/Analysis/array-struct-region.c +++ clang/test/Analysis/array-struct-region.c @@ -353,3 +353,21 @@ // FIXME: Should be TRUE. clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{UNKNOWN}} } + +typedef struct { + int a:1; + int b[2]; +} BITFIELD_CAST; + +int array_struct_bitfield_1() { + BITFIELD_CAST ff = {0}; + BITFIELD_CAST* pff = &ff; + return *((int*)pff + 1); +} + +int array_struct_bitfield_2() { + BITFIELD_CAST ff = {0}; + BITFIELD_CAST* pff = &ff; + int a = *((int*)pff + 2); // expected-warning{{Assigned value is garbage or undefined [core.uninitialized.Assign]}} + return a; +} Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2153,8 +2153,13 @@ return UnknownVal(); // Additionally allow introspection of a block's internal layout. - if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion())) + // Try to get direct binding if all other attempts failed thus far. + // Else, return UndefinedVal() + if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion())) { + if (const Optional<SVal> &V = B.getDefaultBinding(R)) + return *V; return UndefinedVal(); + } } // All other values are symbolic.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits