forked from OSchip/llvm-project
Revert "Add a new attribute, fortify_stdlib"
This reverts commit r353765. After talking with our c stdlib folks, we decided to use the existing pass_object_size attribute to implement _FORTIFY_SOURCE wrappers, like Bionic does (I didn't realize that pass_object_size could be used for this purpose). Sorry for the flip/flop, and thanks to James Y. Knight for pointing this out to me. llvm-svn: 356103
This commit is contained in:
parent
a688a42cdd
commit
02886e5476
|
@ -1566,13 +1566,6 @@ def PassObjectSize : InheritableParamAttr {
|
|||
let Documentation = [PassObjectSizeDocs];
|
||||
}
|
||||
|
||||
def FortifyStdLib : InheritableAttr {
|
||||
let Spellings = [Clang<"fortify_stdlib">];
|
||||
let Args = [IntArgument<"Type">, IntArgument<"Flag">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [FortifyStdLibDocs];
|
||||
}
|
||||
|
||||
// Nullability type attributes.
|
||||
def TypeNonNull : TypeAttr {
|
||||
let Spellings = [Keyword<"_Nonnull">];
|
||||
|
|
|
@ -965,43 +965,6 @@ of the condition.
|
|||
}];
|
||||
}
|
||||
|
||||
def FortifyStdLibDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``fortify_stdlib`` attribute applies to declarations of C stdlib functions
|
||||
(memcpy, sprintf, ...), and causes clang to emit calls to their fortified
|
||||
variants with ``__builtin_object_size``. This attribute is intended for use
|
||||
within standard C library implementations and should not generally be used for
|
||||
user applications. For instance:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
__attribute__((fortify_stdlib(0, 0)))
|
||||
int sprintf(char *buf, const char *fmt, ...);
|
||||
|
||||
int main() {
|
||||
char buf[5];
|
||||
sprintf(buf, "%f", 42.0);
|
||||
// Clang generates code equivalent to:
|
||||
// __sprintf_chk(buf, 0, __builtin_object_size(0), "%f", 42.0);
|
||||
}
|
||||
|
||||
The first argument to the attribute is the integer `type` argument passed to
|
||||
`__builtin_object_size` (you can read more about `__builtin_object_size`
|
||||
`here <https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Object-Size-Checking.html>`_),
|
||||
The second argument to this attribute is the flag that the fortified format
|
||||
functions accept.
|
||||
|
||||
Only a specific set of standard library functions are supported:
|
||||
- memcpy, memmove, memset
|
||||
- stpcpy, strcat, strcpy
|
||||
- strlcat, strlcpy
|
||||
- strncat, strncpy, stpncpy
|
||||
- snprintf, vsnprintf, sprintf, vsprintf
|
||||
- fprintf, vfprintf, printf, vprintf
|
||||
}];
|
||||
}
|
||||
|
||||
def ConvergentDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
|
|
|
@ -242,13 +242,7 @@ private:
|
|||
const char *Fmt) const;
|
||||
};
|
||||
|
||||
/// For a given BuiltinID, return the ID of the fortified variant function. For
|
||||
/// instance, if Builtin::BIsprintf is passed, this function will return
|
||||
/// Builtin::BI__builtin___sprintf_chk. If BuiltinID doesn't have a fortified
|
||||
/// variant, 0 is returned.
|
||||
unsigned getFortifiedVariantFunction(unsigned BuiltinID);
|
||||
|
||||
} // end namespace Builtin
|
||||
}
|
||||
|
||||
/// Kinds of BuiltinTemplateDecl.
|
||||
enum BuiltinTemplateKind : int {
|
||||
|
|
|
@ -4826,8 +4826,6 @@ def ext_ms_forward_ref_enum : ExtWarn<
|
|||
def ext_forward_ref_enum_def : Extension<
|
||||
"redeclaration of already-defined enum %0 is a GNU extension">,
|
||||
InGroup<GNURedeclaredEnum>;
|
||||
def err_fortify_std_lib_bad_decl : Error<
|
||||
"'fortify_stdlib' attribute applied to an unknown function">;
|
||||
|
||||
def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
|
||||
def err_duplicate_member : Error<"duplicate member %0">;
|
||||
|
|
|
@ -188,28 +188,3 @@ bool Builtin::Context::canBeRedeclared(unsigned ID) const {
|
|||
(!hasReferenceArgsOrResult(ID) &&
|
||||
!hasCustomTypechecking(ID));
|
||||
}
|
||||
|
||||
unsigned Builtin::getFortifiedVariantFunction(unsigned BuiltinID) {
|
||||
switch (BuiltinID) {
|
||||
case Builtin::BImemcpy: return Builtin::BI__builtin___memcpy_chk;
|
||||
case Builtin::BImemmove: return Builtin::BI__builtin___memmove_chk;
|
||||
case Builtin::BImemset: return Builtin::BI__builtin___memset_chk;
|
||||
case Builtin::BIstpcpy: return Builtin::BI__builtin___stpcpy_chk;
|
||||
case Builtin::BIstrcat: return Builtin::BI__builtin___strcat_chk;
|
||||
case Builtin::BIstrcpy: return Builtin::BI__builtin___strcpy_chk;
|
||||
case Builtin::BIstrlcat: return Builtin::BI__builtin___strlcat_chk;
|
||||
case Builtin::BIstrlcpy: return Builtin::BI__builtin___strlcpy_chk;
|
||||
case Builtin::BIstrncat: return Builtin::BI__builtin___strncat_chk;
|
||||
case Builtin::BIstrncpy: return Builtin::BI__builtin___strncpy_chk;
|
||||
case Builtin::BIstpncpy: return Builtin::BI__builtin___stpncpy_chk;
|
||||
case Builtin::BIsnprintf: return Builtin::BI__builtin___snprintf_chk;
|
||||
case Builtin::BIvsnprintf: return Builtin::BI__builtin___vsnprintf_chk;
|
||||
case Builtin::BIsprintf: return Builtin::BI__builtin___sprintf_chk;
|
||||
case Builtin::BIvsprintf: return Builtin::BI__builtin___vsprintf_chk;
|
||||
case Builtin::BIfprintf: return Builtin::BI__builtin___fprintf_chk;
|
||||
case Builtin::BIvfprintf: return Builtin::BI__builtin___vfprintf_chk;
|
||||
case Builtin::BIprintf: return Builtin::BI__builtin___printf_chk;
|
||||
case Builtin::BIvprintf: return Builtin::BI__builtin___vprintf_chk;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1474,86 +1474,6 @@ RValue CodeGenFunction::emitRotate(const CallExpr *E, bool IsRotateRight) {
|
|||
return RValue::get(Builder.CreateCall(F, { Src, Src, ShiftAmt }));
|
||||
}
|
||||
|
||||
/// For a call to a builtin C standard library function, emit a call to a
|
||||
/// fortified variant using __builtin_object_size. For instance, instead of
|
||||
/// emitting `sprintf(buf, "%d", 32)`, this function would emit
|
||||
/// `__sprintf_chk(buf, Flag, __builtin_object_size(buf, 0), "%d", 32)`.
|
||||
RValue CodeGenFunction::emitFortifiedStdLibCall(CodeGenFunction &CGF,
|
||||
const CallExpr *CE,
|
||||
unsigned BuiltinID,
|
||||
unsigned BOSType,
|
||||
unsigned Flag) {
|
||||
SmallVector<llvm::Value *, 8> ArgVals;
|
||||
for (const Expr *Arg : CE->arguments())
|
||||
ArgVals.push_back(EmitScalarExpr(Arg));
|
||||
|
||||
llvm::Value *FlagVal = llvm::ConstantInt::get(IntTy, Flag);
|
||||
auto emitObjSize = [&]() {
|
||||
return evaluateOrEmitBuiltinObjectSize(CE->getArg(0), BOSType, SizeTy,
|
||||
ArgVals[0], false);
|
||||
};
|
||||
|
||||
unsigned FortifiedVariantID = Builtin::getFortifiedVariantFunction(BuiltinID);
|
||||
assert(FortifiedVariantID != 0 && "Should be diagnosed in Sema");
|
||||
|
||||
// Adjust ArgVals to include a __builtin_object_size(n) or flag argument at
|
||||
// the right position. Variadic printf-like functions take a flag and object
|
||||
// size (if they're printing to a string) before the format string, and all
|
||||
// other functions just take the object size as their last argument. The
|
||||
// object size, if present, always corresponds to the first argument.
|
||||
switch (BuiltinID) {
|
||||
case Builtin::BImemcpy:
|
||||
case Builtin::BImemmove:
|
||||
case Builtin::BImemset:
|
||||
case Builtin::BIstpcpy:
|
||||
case Builtin::BIstrcat:
|
||||
case Builtin::BIstrcpy:
|
||||
case Builtin::BIstrlcat:
|
||||
case Builtin::BIstrlcpy:
|
||||
case Builtin::BIstrncat:
|
||||
case Builtin::BIstrncpy:
|
||||
case Builtin::BIstpncpy:
|
||||
ArgVals.push_back(emitObjSize());
|
||||
break;
|
||||
|
||||
case Builtin::BIsnprintf:
|
||||
case Builtin::BIvsnprintf:
|
||||
ArgVals.insert(ArgVals.begin() + 2, FlagVal);
|
||||
ArgVals.insert(ArgVals.begin() + 3, emitObjSize());
|
||||
break;
|
||||
|
||||
case Builtin::BIsprintf:
|
||||
case Builtin::BIvsprintf:
|
||||
ArgVals.insert(ArgVals.begin() + 1, FlagVal);
|
||||
ArgVals.insert(ArgVals.begin() + 2, emitObjSize());
|
||||
break;
|
||||
|
||||
case Builtin::BIfprintf:
|
||||
case Builtin::BIvfprintf:
|
||||
ArgVals.insert(ArgVals.begin() + 1, FlagVal);
|
||||
break;
|
||||
|
||||
case Builtin::BIprintf:
|
||||
case Builtin::BIvprintf:
|
||||
ArgVals.insert(ArgVals.begin(), FlagVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
llvm_unreachable("Unknown fortified builtin?");
|
||||
}
|
||||
|
||||
ASTContext::GetBuiltinTypeError Err;
|
||||
QualType VariantTy = getContext().GetBuiltinType(FortifiedVariantID, Err);
|
||||
assert(Err == ASTContext::GE_None && "Should not codegen an error");
|
||||
auto *LLVMVariantTy = cast<llvm::FunctionType>(ConvertType(VariantTy));
|
||||
StringRef VariantName = getContext().BuiltinInfo.getName(FortifiedVariantID) +
|
||||
strlen("__builtin_");
|
||||
|
||||
llvm::Value *V = Builder.CreateCall(
|
||||
CGM.CreateRuntimeFunction(LLVMVariantTy, VariantName), ArgVals);
|
||||
return RValue::get(V);
|
||||
}
|
||||
|
||||
RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
||||
const CallExpr *E,
|
||||
ReturnValueSlot ReturnValue) {
|
||||
|
@ -1570,10 +1490,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
|||
Result.Val.getFloat()));
|
||||
}
|
||||
|
||||
if (const auto *FortifyAttr = FD->getAttr<FortifyStdLibAttr>())
|
||||
return emitFortifiedStdLibCall(*this, E, BuiltinID, FortifyAttr->getType(),
|
||||
FortifyAttr->getFlag());
|
||||
|
||||
// There are LLVM math intrinsics/instructions corresponding to math library
|
||||
// functions except the LLVM op will never set errno while the math library
|
||||
// might. Also, math builtins have the same semantics as their math library
|
||||
|
|
|
@ -3697,10 +3697,6 @@ public:
|
|||
RValue EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
||||
const CallExpr *E, ReturnValueSlot ReturnValue);
|
||||
|
||||
RValue emitFortifiedStdLibCall(CodeGenFunction &CGF, const CallExpr *CE,
|
||||
unsigned BuiltinID, unsigned BOSType,
|
||||
unsigned Flag);
|
||||
|
||||
RValue emitRotate(const CallExpr *E, bool IsRotateRight);
|
||||
|
||||
/// Emit IR for __builtin_os_log_format.
|
||||
|
|
|
@ -6524,31 +6524,6 @@ static void handleObjCExternallyRetainedAttr(Sema &S, Decl *D,
|
|||
handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
|
||||
}
|
||||
|
||||
static void handleFortifyStdLib(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
auto *FD = cast<FunctionDecl>(D);
|
||||
unsigned VariantID = Builtin::getFortifiedVariantFunction(FD->getBuiltinID());
|
||||
if (VariantID == 0) {
|
||||
S.Diag(D->getLocation(), diag::err_fortify_std_lib_bad_decl);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t BOSType, Flag;
|
||||
if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), BOSType, 0, true) ||
|
||||
!checkUInt32Argument(S, AL, AL.getArgAsExpr(1), Flag, 1, true))
|
||||
return;
|
||||
|
||||
if (BOSType > 3) {
|
||||
S.Diag(AL.getArgAsExpr(0)->getBeginLoc(),
|
||||
diag::err_attribute_argument_out_of_range)
|
||||
<< AL << 0 << 3;
|
||||
return;
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.getASTContext()) FortifyStdLibAttr(
|
||||
AL.getLoc(), S.getASTContext(), BOSType, Flag,
|
||||
AL.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static void handleMIGServerRoutineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
// Check that the return type is a `typedef int kern_return_t` or a typedef
|
||||
// around it, because otherwise MIG convention checks make no sense.
|
||||
|
@ -7301,10 +7276,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
|||
handleObjCExternallyRetainedAttr(S, D, AL);
|
||||
break;
|
||||
|
||||
case ParsedAttr::AT_FortifyStdLib:
|
||||
handleFortifyStdLib(S, D, AL);
|
||||
break;
|
||||
|
||||
case ParsedAttr::AT_MIGServerRoutine:
|
||||
handleMIGServerRoutineAttr(S, D, AL);
|
||||
break;
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -emit-llvm -O0 -disable-llvm-passes -o - -Wno-format-security | FileCheck %s
|
||||
// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -emit-llvm -O0 -disable-llvm-passes -o - -Wno-format-security | FileCheck %s
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
#else
|
||||
#define EXTERN
|
||||
#endif
|
||||
|
||||
#define FSL(x,y) __attribute__((fortify_stdlib(x,y)))
|
||||
typedef unsigned long size_t;
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
void *memcpy(void *dst, const void *src, size_t sz);
|
||||
|
||||
EXTERN
|
||||
void call_memcpy(void *dst, const void *src, size_t sz) {
|
||||
memcpy(dst, src, sz);
|
||||
// CHECK-LABEL: define void @call_memcpy
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__memcpy_chk(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
void *memmove(void *dst, const void *src, size_t sz);
|
||||
|
||||
EXTERN
|
||||
void call_memmove(void *dst, const void *src, size_t sz) {
|
||||
memmove(dst, src, sz);
|
||||
// CHECK-LABEL: define void @call_memmove
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__memmove_chk(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
void *memset(void *dst, int c, size_t sz);
|
||||
|
||||
EXTERN
|
||||
void call_memset(void *dst, int c, size_t sz) {
|
||||
memset(dst, c, sz);
|
||||
// CHECK-LABEL: define void @call_memset
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__memset_chk(i8* {{.*}}, i32 {{.*}}, i64 {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
char *stpcpy(char* dst, const char *src);
|
||||
|
||||
EXTERN
|
||||
void call_stpcpy(char *dst, const char *src) {
|
||||
stpcpy(dst, src);
|
||||
// CHECK-LABEL: define void @call_stpcpy
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__stpcpy_chk(i8* {{.*}}, i8* {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
char *strcat(char* dst, const char *src);
|
||||
|
||||
EXTERN
|
||||
void call_strcat(char *dst, const char *src) {
|
||||
strcat(dst, src);
|
||||
// CHECK-LABEL: define void @call_strcat
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__strcat_chk(i8* {{.*}}, i8* {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
char *strcpy(char* dst, const char *src);
|
||||
|
||||
EXTERN
|
||||
void call_strcpy(char *dst, const char *src) {
|
||||
strcpy(dst, src);
|
||||
// CHECK-LABEL: define void @call_strcpy
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__strcpy_chk(i8* {{.*}}, i8* {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
size_t strlcat(char* dst, const char *src, size_t len);
|
||||
|
||||
EXTERN
|
||||
void call_strlcat(char *dst, const char *src, size_t len) {
|
||||
strlcat(dst, src, len);
|
||||
// CHECK-LABEL: define void @call_strlcat
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i64 @__strlcat_chk(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
size_t strlcpy(char* dst, const char *src, size_t len);
|
||||
|
||||
EXTERN
|
||||
void call_strlcpy(char *dst, const char *src, size_t len) {
|
||||
strlcpy(dst, src, len);
|
||||
// CHECK-LABEL: define void @call_strlcpy
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i64 @__strlcpy_chk(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
char *strncat(char* dst, const char *src, size_t len);
|
||||
|
||||
EXTERN
|
||||
void call_strncat(char *dst, const char *src, size_t len) {
|
||||
strncat(dst, src, len);
|
||||
// CHECK-LABEL: define void @call_strncat
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__strncat_chk(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
char *strncpy(char* dst, const char *src, size_t len);
|
||||
|
||||
EXTERN
|
||||
void call_strncpy(char *dst, const char *src, size_t len) {
|
||||
strncpy(dst, src, len);
|
||||
// CHECK-LABEL: define void @call_strncpy
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__strncpy_chk(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
char *stpncpy(char* dst, const char *src, size_t len);
|
||||
|
||||
EXTERN
|
||||
void call_stpncpy(char *dst, const char *src, size_t len) {
|
||||
stpncpy(dst, src, len);
|
||||
// CHECK-LABEL: define void @call_stpncpy
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i8* @__stpncpy_chk(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i64 [[REG]])
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
int snprintf(char *buf, size_t n, const char *fmt, ...);
|
||||
|
||||
EXTERN
|
||||
void call_snprintf(char *buf, size_t n, const char *fmt) {
|
||||
snprintf(buf, n, fmt);
|
||||
// CHECK-LABEL: define void @call_snprintf
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* {{.*}}, i64 {{.*}}, i32 0, i64 [[REG]]
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
int vsnprintf(char *buf, size_t n, const char *fmt, __builtin_va_list lst);
|
||||
|
||||
EXTERN
|
||||
void call_vsnprintf(char *buf, size_t n, const char *fmt, __builtin_va_list lst) {
|
||||
vsnprintf(buf, n, fmt, lst);
|
||||
// CHECK-LABEL: define void @call_vsnprintf
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i32 @__vsnprintf_chk(i8* {{.*}}, i64 {{.*}}, i32 0, i64 [[REG]]
|
||||
}
|
||||
|
||||
FSL(0,0) EXTERN
|
||||
int sprintf(char *buf, const char *fmt, ...);
|
||||
|
||||
void call_sprintf(char *buf, const char* fmt) {
|
||||
sprintf(buf, fmt);
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* {{.*}}, i32 0, i64 [[REG]]
|
||||
sprintf(buf, fmt, 1, 2, 3);
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* {{.*}}, i32 0, i64 [[REG]], i8* {{.*}}, i32 1, i32 2, i32 3)
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
int vsprintf(char *buf, const char *fmt, __builtin_va_list lst);
|
||||
|
||||
EXTERN
|
||||
void call_vsprintf(char *buf, const char *fmt, __builtin_va_list lst) {
|
||||
vsprintf(buf, fmt, lst);
|
||||
// CHECK-LABEL: define void @call_vsprintf
|
||||
// CHECK: [[REG:%[0-9]+]] = call i64 @llvm.objectsize.i64.p0i8(i8*{{.*}}, i1 false, i1 true, i1 false)
|
||||
// CHECK: call i32 @__vsprintf_chk(i8* {{.*}}, i32 0, i64 [[REG]]
|
||||
}
|
||||
|
||||
typedef struct {} FILE;
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
int fprintf(FILE *file, const char *fmt, ...);
|
||||
|
||||
EXTERN
|
||||
void call_fprintf(FILE *file, const char *fmt) {
|
||||
fprintf(file, fmt);
|
||||
// CHECK-LABEL: define void @call_fprintf
|
||||
// CHECK: call i32 ({{.*}}*, i32, i8*, ...) @__fprintf_chk({{.*}}, i32 0, i8* {{.*}})
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
int vfprintf(FILE *file, const char *fmt, __builtin_va_list lst);
|
||||
|
||||
EXTERN
|
||||
void call_vfprintf(FILE *file, const char *fmt, __builtin_va_list lst) {
|
||||
vfprintf(file, fmt, lst);
|
||||
// CHECK-LABEL: define void @call_vfprintf
|
||||
// CHECK: call i32 @__vfprintf_chk({{.*}}, i32 0, i8* {{.*}}, {{.*}})
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
int printf(const char *fmt, ...);
|
||||
|
||||
EXTERN
|
||||
void call_printf(const char *fmt) {
|
||||
printf(fmt);
|
||||
// CHECK-LABEL: define void @call_printf
|
||||
// CHECK: call i32 (i32, i8*, ...) @__printf_chk(i32 0, i8* {{.*}})
|
||||
}
|
||||
|
||||
FSL(0, 0) EXTERN
|
||||
int vprintf(const char *fmt, __builtin_va_list lst);
|
||||
|
||||
EXTERN
|
||||
void call_vprintf(const char *fmt, __builtin_va_list lst) {
|
||||
vprintf(fmt, lst);
|
||||
// CHECK-LABEL: define void @call_vprintf
|
||||
// CHECK: call i32 @__vprintf_chk(i32 0, {{.*}})
|
||||
}
|
||||
|
|
@ -52,7 +52,6 @@
|
|||
// CHECK-NEXT: ExternalSourceSymbol ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
|
||||
// CHECK-NEXT: FlagEnum (SubjectMatchRule_enum)
|
||||
// CHECK-NEXT: Flatten (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: FortifyStdLib (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: GNUInline (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: Hot (SubjectMatchRule_function)
|
||||
// CHECK-NEXT: IBAction (SubjectMatchRule_objc_method_is_instance)
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 -fsyntax-only %s -verify
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
__attribute__((fortify_stdlib(0, 0)))
|
||||
int not_anything_special(); // expected-error {{'fortify_stdlib' attribute applied to an unknown function}}
|
||||
|
||||
__attribute__((fortify_stdlib(4, 0))) // expected-error {{'fortify_stdlib' attribute requires integer constant between 0 and 3 inclusive}}
|
||||
int sprintf(char *, const char *, ...);
|
||||
|
||||
__attribute__((fortify_stdlib())) // expected-error {{'fortify_stdlib' attribute requires exactly 2 arguments}}
|
||||
int sprintf(char *, const char *, ...);
|
||||
|
||||
__attribute__((fortify_stdlib(1, 2, 3))) // expected-error {{'fortify_stdlib' attribute requires exactly 2 arguments}}
|
||||
int sprintf(char *, const char *, ...);
|
||||
|
||||
__attribute__((fortify_stdlib(-1, 2))) // expected-error {{'fortify_stdlib' attribute requires a non-negative integral compile time constant expression}}
|
||||
int sprintf(char *, const char *, ...);
|
Loading…
Reference in New Issue