Author: Balazs Benics Date: 2021-08-25T17:19:06+02:00 New Revision: e5646b9254e0150e7897bd2658fa0b19eef39070
URL: https://github.com/llvm/llvm-project/commit/e5646b9254e0150e7897bd2658fa0b19eef39070 DIFF: https://github.com/llvm/llvm-project/commit/e5646b9254e0150e7897bd2658fa0b19eef39070.diff LOG: Revert "Revert "[analyzer] Ignore IncompleteArrayTypes in getStaticSize() for FAMs"" This reverts commit df1f4e0cc6ec9a734aae41ffd48ee8b2007fcabb. Now the test case explicitly specifies the target triple. I decided to use x86_64 for that matter, to have a fixed bitwidth for `size_t`. Aside from that, relanding the original changes of: https://reviews.llvm.org/D105184 Added: clang/test/Analysis/flexible-array-members.c Modified: clang/lib/StaticAnalyzer/Core/MemRegion.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index bd725ee9eaa36..1a614d4d2bcdb 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -768,14 +768,27 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, return UnknownVal(); QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx); - DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB); + const DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB); // A zero-length array at the end of a struct often stands for dynamically // allocated extra memory. - if (Size.isZeroConstant()) { - if (isa<ConstantArrayType>(Ty)) - return UnknownVal(); - } + const auto isFlexibleArrayMemberCandidate = [this](QualType Ty) -> bool { + const ArrayType *AT = Ctx.getAsArrayType(Ty); + if (!AT) + return false; + if (isa<IncompleteArrayType>(AT)) + return true; + + if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) { + const llvm::APInt &Size = CAT->getSize(); + if (Size.isNullValue()) + return true; + } + return false; + }; + + if (isFlexibleArrayMemberCandidate(Ty)) + return UnknownVal(); return Size; } diff --git a/clang/test/Analysis/flexible-array-members.c b/clang/test/Analysis/flexible-array-members.c new file mode 100644 index 0000000000000..6200ed6d41d27 --- /dev/null +++ b/clang/test/Analysis/flexible-array-members.c @@ -0,0 +1,96 @@ +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c90 +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c99 +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c11 +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c17 + +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++98 -x c++ +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++03 -x c++ +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++11 -x c++ +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++14 -x c++ +// RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++17 -x c++ + +typedef __typeof(sizeof(int)) size_t; +size_t clang_analyzer_getExtent(void *); +void clang_analyzer_dump(size_t); + +void *alloca(size_t size); +void *malloc(size_t size); +void free(void *ptr); + +void test_incomplete_array_fam() { + typedef struct FAM { + char c; + int data[]; + } FAM; + + FAM fam; + clang_analyzer_dump(clang_analyzer_getExtent(&fam)); + clang_analyzer_dump(clang_analyzer_getExtent(fam.data)); + // expected-warning@-2 {{4 S64b}} + // expected-warning@-2 {{Unknown}} + + FAM *p = (FAM *)alloca(sizeof(FAM)); + clang_analyzer_dump(clang_analyzer_getExtent(p)); + clang_analyzer_dump(clang_analyzer_getExtent(p->data)); + // expected-warning@-2 {{4 U64b}} + // expected-warning@-2 {{Unknown}} + + FAM *q = (FAM *)malloc(sizeof(FAM)); + clang_analyzer_dump(clang_analyzer_getExtent(q)); + clang_analyzer_dump(clang_analyzer_getExtent(q->data)); + // expected-warning@-2 {{4 U64b}} + // expected-warning@-2 {{Unknown}} + free(q); +} + +void test_zero_length_array_fam() { + typedef struct FAM { + char c; + int data[0]; + } FAM; + + FAM fam; + clang_analyzer_dump(clang_analyzer_getExtent(&fam)); + clang_analyzer_dump(clang_analyzer_getExtent(fam.data)); + // expected-warning@-2 {{4 S64b}} + // expected-warning@-2 {{Unknown}} + + FAM *p = (FAM *)alloca(sizeof(FAM)); + clang_analyzer_dump(clang_analyzer_getExtent(p)); + clang_analyzer_dump(clang_analyzer_getExtent(p->data)); + // expected-warning@-2 {{4 U64b}} + // expected-warning@-2 {{Unknown}} + + FAM *q = (FAM *)malloc(sizeof(FAM)); + clang_analyzer_dump(clang_analyzer_getExtent(q)); + clang_analyzer_dump(clang_analyzer_getExtent(q->data)); + // expected-warning@-2 {{4 U64b}} + // expected-warning@-2 {{Unknown}} + free(q); +} + +void test_single_element_array_possible_fam() { + typedef struct FAM { + char c; + int data[1]; + } FAM; + + FAM likely_fam; + clang_analyzer_dump(clang_analyzer_getExtent(&likely_fam)); + clang_analyzer_dump(clang_analyzer_getExtent(likely_fam.data)); + // expected-warning@-2 {{8 S64b}} + // expected-warning@-2 {{4 S64b}} + + FAM *p = (FAM *)alloca(sizeof(FAM)); + clang_analyzer_dump(clang_analyzer_getExtent(p)); + clang_analyzer_dump(clang_analyzer_getExtent(p->data)); + // expected-warning@-2 {{8 U64b}} + // expected-warning@-2 {{4 S64b}} + + FAM *q = (FAM *)malloc(sizeof(FAM)); + clang_analyzer_dump(clang_analyzer_getExtent(q)); + clang_analyzer_dump(clang_analyzer_getExtent(q->data)); + // expected-warning@-2 {{8 U64b}} + // expected-warning@-2 {{4 S64b}} + free(q); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits