From f5e89b280d0aca5a2e62752f54d9f58e45ac4e7d Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Fri, 4 May 2018 22:11:12 +0000 Subject: [PATCH] [analyzer] pr36458: Fix retrieved value cast for symbolic void pointers. C allows us to write any bytes into any memory region. When loading weird bytes from memory regions of known types, the analyzer is required to make sure that the loaded value makes sense by casting it to an appropriate type. Fix such cast for loading values that represent void pointers from non-void pointer type places. Differential Revision: https://reviews.llvm.org/D46415 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331562 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/Store.cpp | 14 ++++++++++++++ test/Analysis/casts.c | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index eeafaf6108..5ab5c08226 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -378,6 +378,20 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R, if (castTy.isNull() || V.isUnknownOrUndef()) return V; + // When retrieving symbolic pointer and expecting a non-void pointer, + // wrap them into element regions of the expected type if necessary. + // SValBuilder::dispatchCast() doesn't do that, but it is necessary to + // make sure that the retrieved value makes sense, because there's no other + // cast in the AST that would tell us to cast it to the correct pointer type. + // We might need to do that for non-void pointers as well. + // FIXME: We really need a single good function to perform casts for us + // correctly every time we need it. + if (castTy->isPointerType() && !castTy->isVoidPointerType()) + if (const auto *SR = dyn_cast_or_null(V.getAsRegion())) + if (SR->getSymbol()->getType().getCanonicalType() != + castTy.getCanonicalType()) + return loc::MemRegionVal(castRegion(SR, castTy)); + return svalBuilder.dispatchCast(V, castTy); } diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c index 24bba8a30a..548b4223b6 100644 --- a/test/Analysis/casts.c +++ b/test/Analysis/casts.c @@ -149,3 +149,25 @@ void multiDimensionalArrayPointerCasts() { clang_analyzer_eval(*((char *)y1) == *((char *) y3)); // expected-warning{{TRUE}} } + +void *getVoidPtr(); + +void testCastVoidPtrToIntPtrThroughIntTypedAssignment() { + int *x; + (*((int *)(&x))) = (int)getVoidPtr(); + *x = 1; // no-crash +} + +void testCastUIntPtrToIntPtrThroughIntTypedAssignment() { + unsigned u; + int *x; + (*((int *)(&x))) = (int)&u; + *x = 1; + clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} +} + +void testCastVoidPtrToIntPtrThroughUIntTypedAssignment() { + int *x; + (*((int *)(&x))) = (int)(unsigned *)getVoidPtr(); + *x = 1; // no-crash +} -- 2.49.0