diff options
-rw-r--r-- | lib/Analysis/Store.cpp | 10 | ||||
-rw-r--r-- | test/Analysis/misc-ps.m | 8 |
2 files changed, 15 insertions, 3 deletions
diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp index bfcb0f41ca..fca69e69cb 100644 --- a/lib/Analysis/Store.cpp +++ b/lib/Analysis/Store.cpp @@ -71,13 +71,17 @@ StoreManager::CastRegion(const GRState *state, const MemRegion* R, // Now assume we are casting from pointer to pointer. Other cases should // already be handled. QualType PointeeTy = CastToTy->getAs<PointerType>()->getPointeeType(); + QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); + + // Handle casts to void*. We just pass the region through. + if (CanonPointeeTy.getUnqualifiedType() == Ctx.VoidTy) + return CastResult(state, R); - // Handle casts from compatible types or to void*. + // Handle casts from compatible types. if (R->isBoundable()) if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) { QualType ObjTy = Ctx.getCanonicalType(TR->getValueType(Ctx)); - QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); - if (CanonPointeeTy == ObjTy || CanonPointeeTy == Ctx.VoidTy) + if (CanonPointeeTy == ObjTy) return CastResult(state, R); } diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 1b16762c42..c4fa7a8a1d 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -491,3 +491,11 @@ void test_invalidate_cast_int() { static NSNumber *test_ivar_offset(id self, SEL _cmd, Ivar inIvar) { return [[[NSNumber allocWithZone:((void*)0)] initWithBool:*(_Bool *)((char *)self + ivar_getOffset(inIvar))] autorelease]; } + +// Reduced from a crash in StoreManager::CastRegion involving a divide-by-zero. +// This resulted from not properly handling region casts to 'const void*'. +void test_cast_const_voidptr() { + char x[10]; + char *p = &x[1]; + const void* q = p; +} |