Simple inline allocation wrappers have been preventing AllocToken coverage for such callsites. Instead of converting such inline wrappers to macros, we can support covering standard allocation calls in inline allocation wrappers when inlined. When an allocation wrapper with malloc/alloc_size attributes is inlined, propagate its call-site !alloc_token onto return-value producing calls exposed by inlining, so the late AllocToken pass assigns the correct type-derived token even in default (non-extended) mode. Propagation is restricted to calls producing the return-value(s) that the wrapper actually returns. This keeps unrelated calls in the wrapper body unchanged, which matters under -fsanitize-alloc-token-extended, where any !alloc_token-carrying call is instrumented.
28 lines
1.0 KiB
C
28 lines
1.0 KiB
C
// RUN: %clang_cc1 -O -fsanitize=alloc-token -fsanitize-alloc-token-extended -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --implicit-check-not=__alloc_token
|
|
// RUN: %clang_cc1 -O -fsanitize=alloc-token -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --implicit-check-not=__alloc_token
|
|
|
|
typedef __typeof(sizeof(int)) size_t;
|
|
|
|
void *sink;
|
|
|
|
void *malloc(size_t size);
|
|
void *external_ptr_helper(void);
|
|
void external_void_helper(void);
|
|
|
|
__attribute__((malloc, always_inline)) inline void *wrapper(size_t size) {
|
|
sink = external_ptr_helper();
|
|
external_void_helper();
|
|
return malloc(size);
|
|
}
|
|
|
|
// CHECK-LABEL: @test_inlined_wrapper(
|
|
// CHECK: call ptr @external_ptr_helper()
|
|
// CHECK: call void @external_void_helper()
|
|
// CHECK: call{{.*}} @__alloc_token_malloc(i64 noundef 4, i64 2689373973731826898){{.*}} !alloc_token [[META_INT:![0-9]+]]
|
|
void test_inlined_wrapper(void) {
|
|
sink = wrapper(sizeof(int));
|
|
}
|
|
|
|
// CHECK: declare{{.*}} @__alloc_token_malloc(
|
|
// CHECK: [[META_INT]] = !{!"int", i1 false}
|