https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/97199
We can get zero type size (thus div by zero crash) if the region is for a 'void*' pointer. In this patch, let's just override the void type with a char type to avoid the crash. Fixes https://github.com/llvm/llvm-project/pull/93408#issuecomment-2189766510 >From 81910b6d8139868304c87784416e087e2aea9f7a Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Sun, 30 Jun 2024 11:32:14 +0200 Subject: [PATCH] [analyzer] Fix crash in Stream checker when using void pointers We can get zero type size (thus div by zero crash) if the region is for a 'void*' pointer. In this patch, let's just override the void type with a char type to avoid the crash. Fixes https://github.com/llvm/llvm-project/pull/93408#issuecomment-2189766510 --- .../StaticAnalyzer/Checkers/StreamChecker.cpp | 39 ++++++++++++------- clang/test/Analysis/stream.c | 13 +++++++ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 9aee7f952ad2d..0d1d50d19f4c4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -1034,16 +1034,19 @@ void StreamChecker::preWrite(const FnDescription *Desc, const CallEvent &Call, C.addTransition(State); } -static std::optional<QualType> getPointeeType(const MemRegion *R) { +static QualType getPointeeType(const MemRegion *R) { if (!R) - return std::nullopt; - if (const auto *ER = dyn_cast<ElementRegion>(R)) - return ER->getElementType(); - if (const auto *TR = dyn_cast<TypedValueRegion>(R)) - return TR->getValueType(); - if (const auto *SR = dyn_cast<SymbolicRegion>(R)) - return SR->getPointeeStaticType(); - return std::nullopt; + return {}; + QualType Ty = [R] { + if (const auto *ER = dyn_cast<ElementRegion>(R)) + return ER->getElementType(); + if (const auto *TR = dyn_cast<TypedValueRegion>(R)) + return TR->getValueType(); + if (const auto *SR = dyn_cast<SymbolicRegion>(R)) + return SR->getPointeeStaticType(); + return QualType{}; + }(); + return !Ty.isNull() ? Ty->getCanonicalTypeUnqualified() : QualType{}; } static std::optional<NonLoc> getStartIndex(SValBuilder &SVB, @@ -1073,7 +1076,16 @@ tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C, const auto *Buffer = dyn_cast_or_null<SubRegion>(Call.getArgSVal(0).getAsRegion()); - std::optional<QualType> ElemTy = getPointeeType(Buffer); + const ASTContext &Ctx = C.getASTContext(); + + QualType ElemTy = getPointeeType(Buffer); + + // Consider pointer to void as a pointer to char buffer such that it has a + // non-zero type size. + if (!ElemTy.isNull() && ElemTy == Ctx.VoidTy) { + ElemTy = Ctx.CharTy; + } + std::optional<SVal> StartElementIndex = getStartIndex(C.getSValBuilder(), Buffer); @@ -1086,10 +1098,9 @@ tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C, std::optional<int64_t> StartIndexVal = getKnownValue(State, StartElementIndex.value_or(UnknownVal())); - if (ElemTy && CountVal && Size && StartIndexVal) { + if (!ElemTy.isNull() && CountVal && Size && StartIndexVal) { int64_t NumBytesRead = Size.value() * CountVal.value(); - int64_t ElemSizeInChars = - C.getASTContext().getTypeSizeInChars(*ElemTy).getQuantity(); + int64_t ElemSizeInChars = Ctx.getTypeSizeInChars(ElemTy).getQuantity(); bool IncompleteLastElement = (NumBytesRead % ElemSizeInChars) != 0; int64_t NumCompleteOrIncompleteElementsRead = NumBytesRead / ElemSizeInChars + IncompleteLastElement; @@ -1097,7 +1108,7 @@ tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C, constexpr int MaxInvalidatedElementsLimit = 64; if (NumCompleteOrIncompleteElementsRead <= MaxInvalidatedElementsLimit) { return escapeByStartIndexAndCount(State, Call, C.blockCount(), Buffer, - *ElemTy, *StartIndexVal, + ElemTy, *StartIndexVal, NumCompleteOrIncompleteElementsRead); } } diff --git a/clang/test/Analysis/stream.c b/clang/test/Analysis/stream.c index db03d90cd8af4..0869b1b325172 100644 --- a/clang/test/Analysis/stream.c +++ b/clang/test/Analysis/stream.c @@ -453,3 +453,16 @@ void getline_buffer_size_negative() { free(buffer); fclose(file); } + +void gh_93408_regression(void *buffer) { + FILE *f = fopen("/tmp/foo.txt", "r"); + fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash: void is treated as char. + fclose(f); +} + +typedef void VOID; +void gh_93408_regression_typedef(VOID *buffer) { + FILE *f = fopen("/tmp/foo.txt", "r"); + fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash: VOID is treated as char. + fclose(f); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits