Author: nlopes Date: Sat May 30 11:11:40 2015 New Revision: 238657 URL: http://llvm.org/viewvc/llvm-project?rev=238657&view=rev Log: ubsan: Check for null pointers given to certain builtins, such as memcpy, memset, memmove, and bzero.
Reviewed by: Richard Smith Differential Revision: http://reviews.llvm.org/D9673 Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp cfe/trunk/lib/CodeGen/CGCall.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.h cfe/trunk/test/CodeGen/catch-undef-behavior.c Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=238657&r1=238656&r2=238657&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Sat May 30 11:11:40 2015 @@ -698,6 +698,8 @@ RValue CodeGenFunction::EmitBuiltinExpr( std::pair<llvm::Value*, unsigned> Dest = EmitPointerWithAlignment(E->getArg(0)); Value *SizeVal = EmitScalarExpr(E->getArg(1)); + EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest.first, Builder.getInt8(0), SizeVal, Dest.second, false); return RValue::get(Dest.first); @@ -710,6 +712,10 @@ RValue CodeGenFunction::EmitBuiltinExpr( EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); unsigned Align = std::min(Dest.second, Src.second); + EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.first), E->getArg(1)->getType(), + E->getArg(1)->getExprLoc(), FD, 1); Builder.CreateMemCpy(Dest.first, Src.first, SizeVal, Align, false); return RValue::get(Dest.first); } @@ -767,6 +773,10 @@ RValue CodeGenFunction::EmitBuiltinExpr( EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); unsigned Align = std::min(Dest.second, Src.second); + EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.first), E->getArg(1)->getType(), + E->getArg(1)->getExprLoc(), FD, 1); Builder.CreateMemMove(Dest.first, Src.first, SizeVal, Align, false); return RValue::get(Dest.first); } @@ -777,6 +787,8 @@ RValue CodeGenFunction::EmitBuiltinExpr( Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); Value *SizeVal = EmitScalarExpr(E->getArg(2)); + EmitNonNullArgCheck(RValue::get(Dest.first), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest.first, ByteVal, SizeVal, Dest.second, false); return RValue::get(Dest.first); } Modified: cfe/trunk/lib/CodeGen/CGCall.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=238657&r1=238656&r2=238657&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGCall.cpp (original) +++ cfe/trunk/lib/CodeGen/CGCall.cpp Sat May 30 11:11:40 2015 @@ -2719,27 +2719,28 @@ void CallArgList::freeArgumentMemory(Cod } } -static void emitNonNullArgCheck(CodeGenFunction &CGF, RValue RV, - QualType ArgType, SourceLocation ArgLoc, - const FunctionDecl *FD, unsigned ParmNum) { - if (!CGF.SanOpts.has(SanitizerKind::NonnullAttribute) || !FD) +void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, + SourceLocation ArgLoc, + const FunctionDecl *FD, + unsigned ParmNum) { + if (!SanOpts.has(SanitizerKind::NonnullAttribute) || !FD) return; auto PVD = ParmNum < FD->getNumParams() ? FD->getParamDecl(ParmNum) : nullptr; unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum; auto NNAttr = getNonNullAttr(FD, PVD, ArgType, ArgNo); if (!NNAttr) return; - CodeGenFunction::SanitizerScope SanScope(&CGF); + SanitizerScope SanScope(this); assert(RV.isScalar()); llvm::Value *V = RV.getScalarVal(); llvm::Value *Cond = - CGF.Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType())); + Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType())); llvm::Constant *StaticData[] = { - CGF.EmitCheckSourceLocation(ArgLoc), - CGF.EmitCheckSourceLocation(NNAttr->getLocation()), - llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1), + EmitCheckSourceLocation(ArgLoc), + EmitCheckSourceLocation(NNAttr->getLocation()), + llvm::ConstantInt::get(Int32Ty, ArgNo + 1), }; - CGF.EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute), + EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute), "nonnull_arg", StaticData, None); } @@ -2767,7 +2768,7 @@ void CodeGenFunction::EmitCallArgs(CallA for (int I = ArgTypes.size() - 1; I >= 0; --I) { CallExpr::const_arg_iterator Arg = ArgBeg + I; EmitCallArg(Args, *Arg, ArgTypes[I]); - emitNonNullArgCheck(*this, Args.back().RV, ArgTypes[I], Arg->getExprLoc(), + EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], Arg->getExprLoc(), CalleeDecl, ParamsToSkip + I); } @@ -2781,7 +2782,7 @@ void CodeGenFunction::EmitCallArgs(CallA CallExpr::const_arg_iterator Arg = ArgBeg + I; assert(Arg != ArgEnd); EmitCallArg(Args, *Arg, ArgTypes[I]); - emitNonNullArgCheck(*this, Args.back().RV, ArgTypes[I], Arg->getExprLoc(), + EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], Arg->getExprLoc(), CalleeDecl, ParamsToSkip + I); } } Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=238657&r1=238656&r2=238657&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat May 30 11:11:40 2015 @@ -2836,6 +2836,11 @@ public: /// conditional branch to it, for the -ftrapv checks. void EmitTrapCheck(llvm::Value *Checked); + /// \brief Create a check for a function parameter that may potentially be + /// declared as non-null. + void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, + const FunctionDecl *FD, unsigned ParmNum); + /// EmitCallArg - Emit a single call argument. void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType); Modified: cfe/trunk/test/CodeGen/catch-undef-behavior.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/catch-undef-behavior.c?rev=238657&r1=238656&r2=238657&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/catch-undef-behavior.c (original) +++ cfe/trunk/test/CodeGen/catch-undef-behavior.c Sat May 30 11:11:40 2015 @@ -371,6 +371,34 @@ void call_decl_nonnull(int *a) { decl_nonnull(a); } +extern void *memcpy (void *, const void *, unsigned) __attribute__((nonnull(1, 2))); + +// CHECK-COMMON-LABEL: @call_memcpy_nonnull +void call_memcpy_nonnull(void *p, void *q, int sz) { + // CHECK-COMMON: icmp ne i8* {{.*}}, null + // CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg + // CHECK-TRAP: call void @llvm.trap() + + // CHECK-COMMON: icmp ne i8* {{.*}}, null + // CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg + // CHECK-TRAP: call void @llvm.trap() + memcpy(p, q, sz); +} + +extern void *memmove (void *, const void *, unsigned) __attribute__((nonnull(1, 2))); + +// CHECK-COMMON-LABEL: @call_memmove_nonnull +void call_memmove_nonnull(void *p, void *q, int sz) { + // CHECK-COMMON: icmp ne i8* {{.*}}, null + // CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg + // CHECK-TRAP: call void @llvm.trap() + + // CHECK-COMMON: icmp ne i8* {{.*}}, null + // CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg + // CHECK-TRAP: call void @llvm.trap() + memmove(p, q, sz); +} + // CHECK-COMMON-LABEL: @call_nonnull_variadic __attribute__((nonnull)) void nonnull_variadic(int a, ...); void call_nonnull_variadic(int a, int *b) { _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
