diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2019-02-11 23:21:39 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2019-02-11 23:21:39 +0000 |
commit | e3cd735ea6378e5dd7765828f560ed49be845a95 (patch) | |
tree | 91101427ae598d9ea6ced7a2e44f0f4f209fe4a9 /clang/test/CodeGen/fortify-std-lib.c | |
parent | 796ac80b863ed92c3d8bcc296f678ff416afc8a8 (diff) | |
download | bcm5719-llvm-e3cd735ea6378e5dd7765828f560ed49be845a95.tar.gz bcm5719-llvm-e3cd735ea6378e5dd7765828f560ed49be845a95.zip |
Add a new attribute, fortify_stdlib
This attribute applies to declarations of C stdlib functions
(sprintf, memcpy...) that have known fortified variants
(__sprintf_chk, __memcpy_chk, ...). When applied, clang will emit
calls to the fortified variant functions instead of calls to the
defaults.
In GCC, this is done by adding gnu_inline-style wrapper functions,
but that doesn't work for us for variadic functions because we don't
support __builtin_va_arg_pack (and have no intention to).
This attribute takes two arguments, the first is 'type' argument
passed through to __builtin_object_size, and the second is a flag
argument that gets passed through to the variadic checking variants.
rdar://47905754
Differential revision: https://reviews.llvm.org/D57918
llvm-svn: 353765
Diffstat (limited to 'clang/test/CodeGen/fortify-std-lib.c')
-rw-r--r-- | clang/test/CodeGen/fortify-std-lib.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/clang/test/CodeGen/fortify-std-lib.c b/clang/test/CodeGen/fortify-std-lib.c new file mode 100644 index 00000000000..f2e170d80bc --- /dev/null +++ b/clang/test/CodeGen/fortify-std-lib.c @@ -0,0 +1,220 @@ +// 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, {{.*}}) +} + |