forked from OSchip/llvm-project
Improve support of GNU mempcpy
- Lower to the memcpy intrinsic - Raise warnings when size/bounds are known Differential Revision: https://reviews.llvm.org/D71374
This commit is contained in:
parent
d27a15fed7
commit
cee4a1c957
|
@ -984,6 +984,7 @@ LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
|
|||
LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_GNU_LANGUAGES)
|
||||
// POSIX string.h
|
||||
LIBBUILTIN(memccpy, "v*v*vC*iz", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(mempcpy, "v*v*vC*z", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
LIBBUILTIN(strdup, "c*cC*", "f", "string.h", ALL_GNU_LANGUAGES)
|
||||
|
|
|
@ -3879,6 +3879,11 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
|
|||
case Builtin::BImemcpy:
|
||||
return Builtin::BImemcpy;
|
||||
|
||||
case Builtin::BI__builtin_mempcpy:
|
||||
case Builtin::BI__builtin___mempcpy_chk:
|
||||
case Builtin::BImempcpy:
|
||||
return Builtin::BImempcpy;
|
||||
|
||||
case Builtin::BI__builtin_memmove:
|
||||
case Builtin::BI__builtin___memmove_chk:
|
||||
case Builtin::BImemmove:
|
||||
|
@ -3936,6 +3941,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
|
|||
return Builtin::BImemset;
|
||||
else if (FnInfo->isStr("memcpy"))
|
||||
return Builtin::BImemcpy;
|
||||
else if (FnInfo->isStr("mempcpy"))
|
||||
return Builtin::BImempcpy;
|
||||
else if (FnInfo->isStr("memmove"))
|
||||
return Builtin::BImemmove;
|
||||
else if (FnInfo->isStr("memcmp"))
|
||||
|
|
|
@ -2500,7 +2500,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
|||
return RValue::get(nullptr);
|
||||
}
|
||||
case Builtin::BImemcpy:
|
||||
case Builtin::BI__builtin_memcpy: {
|
||||
case Builtin::BI__builtin_memcpy:
|
||||
case Builtin::BImempcpy:
|
||||
case Builtin::BI__builtin_mempcpy: {
|
||||
Address Dest = EmitPointerWithAlignment(E->getArg(0));
|
||||
Address Src = EmitPointerWithAlignment(E->getArg(1));
|
||||
Value *SizeVal = EmitScalarExpr(E->getArg(2));
|
||||
|
@ -2509,7 +2511,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
|||
EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(1)->getType(),
|
||||
E->getArg(1)->getExprLoc(), FD, 1);
|
||||
Builder.CreateMemCpy(Dest, Src, SizeVal, false);
|
||||
return RValue::get(Dest.getPointer());
|
||||
if (BuiltinID == Builtin::BImempcpy ||
|
||||
BuiltinID == Builtin::BI__builtin_mempcpy)
|
||||
return RValue::get(Builder.CreateInBoundsGEP(Dest.getPointer(), SizeVal));
|
||||
else
|
||||
return RValue::get(Dest.getPointer());
|
||||
}
|
||||
|
||||
case Builtin::BI__builtin_char_memchr:
|
||||
|
|
|
@ -340,7 +340,8 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
|
|||
case Builtin::BI__builtin___strncat_chk:
|
||||
case Builtin::BI__builtin___strncpy_chk:
|
||||
case Builtin::BI__builtin___stpncpy_chk:
|
||||
case Builtin::BI__builtin___memccpy_chk: {
|
||||
case Builtin::BI__builtin___memccpy_chk:
|
||||
case Builtin::BI__builtin___mempcpy_chk: {
|
||||
DiagID = diag::warn_builtin_chk_overflow;
|
||||
IsChkVariant = true;
|
||||
SizeIndex = TheCall->getNumArgs() - 2;
|
||||
|
@ -379,7 +380,9 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
|
|||
case Builtin::BImemmove:
|
||||
case Builtin::BI__builtin_memmove:
|
||||
case Builtin::BImemset:
|
||||
case Builtin::BI__builtin_memset: {
|
||||
case Builtin::BI__builtin_memset:
|
||||
case Builtin::BImempcpy:
|
||||
case Builtin::BI__builtin_mempcpy: {
|
||||
DiagID = diag::warn_fortify_source_overflow;
|
||||
SizeIndex = TheCall->getNumArgs() - 1;
|
||||
ObjectIndex = 0;
|
||||
|
|
|
@ -222,6 +222,9 @@ void mempcpy2 () {
|
|||
char dst[1];
|
||||
|
||||
mempcpy(dst, src, 4); // expected-warning{{Memory copy function overflows destination buffer}}
|
||||
#ifndef VARIANT
|
||||
// expected-warning@-2{{'mempcpy' will always overflow; destination buffer has size 1, but size argument is 4}}
|
||||
#endif
|
||||
}
|
||||
|
||||
void mempcpy3 () {
|
||||
|
@ -243,6 +246,9 @@ void mempcpy5() {
|
|||
char dst[3];
|
||||
|
||||
mempcpy(dst+2, src+2, 2); // expected-warning{{Memory copy function overflows destination buffer}}
|
||||
#ifndef VARIANT
|
||||
// expected-warning@-2{{'mempcpy' will always overflow; destination buffer has size 1, but size argument is 2}}
|
||||
#endif
|
||||
}
|
||||
|
||||
void mempcpy6() {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: %clang_cc1 -emit-llvm < %s| FileCheck %s
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
void *mempcpy(void *, void const *, size_t);
|
||||
|
||||
char *test(char *d, char *s, size_t n) {
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %[[REG1:[^ ]+]], i8* {{.*}} %1, i64 %[[REG2:[^ ]+]], i1 false)
|
||||
// CHECK-NEXT: %[[REGr:[^ ]+]] = getelementptr inbounds i8, i8* %[[REG1]], i64 %[[REG2]]
|
||||
// CHECK-NEXT: ret i8* %[[REGr]]
|
||||
return mempcpy(d, s, n);
|
||||
}
|
Loading…
Reference in New Issue