diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -748,8 +748,8 @@ // pointers as well. // FIXME: We really need a single good function to perform casts for us // correctly every time we need it. + const MemRegion *R = V.getRegion(); if (CastTy->isPointerType() && !CastTy->isVoidPointerType()) { - const MemRegion *R = V.getRegion(); if (const auto *SR = dyn_cast(R)) { QualType SRTy = SR->getSymbol()->getType(); if (!hasSameUnqualifiedPointeeType(SRTy, CastTy)) { @@ -758,6 +758,13 @@ } } } + // Next fixes pointer dereference using type different from its initial + // one. See PR37503 and PR49007 for details. + if (const auto *ER = dyn_cast(R)) { + R = StateMgr.getStoreManager().castRegion(ER, CastTy); + return loc::MemRegionVal(R); + } + return V; } diff --git a/clang/test/Analysis/casts.c b/clang/test/Analysis/casts.c --- a/clang/test/Analysis/casts.c +++ b/clang/test/Analysis/casts.c @@ -245,3 +245,8 @@ return a * a; } +void no_crash_reinterpret_char_as_uchar(char ***a, int *b) { + *(unsigned char **)a = (unsigned char *)b; + if (**a == 0) // no-crash + ; +} diff --git a/clang/test/Analysis/string.c b/clang/test/Analysis/string.c --- a/clang/test/Analysis/string.c +++ b/clang/test/Analysis/string.c @@ -363,6 +363,20 @@ strcpy(x, y); // no-warning } +// PR37503 +void *get_void_ptr(); +char ***type_punned_ptr; +void strcpy_no_assertion(char c) { + *(unsigned char **)type_punned_ptr = (unsigned char *)(get_void_ptr()); + strcpy(**type_punned_ptr, &c); // no-crash +} + +// PR49007 +char f(char ***c, int *i) { + *(void **)c = i + 1; + return (**c)[0]; // no-crash +} + //===----------------------------------------------------------------------=== // stpcpy() //===----------------------------------------------------------------------===