This is a follow-up related to Inconsistent false positives with Clang CFI sanitizer and function pointers, but it is for a separate issue
Issue
Background
I have an array of structs which store function pointers, which I loop over and call (my real code is more complex than the sample given). To ensure correct behaviour, I enabled CFI with -fsanitize=cfi -fvisiblity=hidden -flto -fcf-protection=full
.
I then started to encounter false positives, where CFI is trapping upon calling these function pointers. These only seem to occur on compilers clang-11
through clang-15
(I will use clang-15
). This also only occurs when -fsanitize=cfi, -fcf-protection=full
are used together.
Issue
Upon calling the first function pointer, it seems to jump to the wrong address, which immediately causes a trap:
$ clang-15 -o main main.c -Wall -Wextra -Wpedantic -O3 -fsanitize=cfi -fvisibility=hidden -flto -fcf-protection=full
$ gdb ./main -ex run
Program received signal SIGTRAP, Trace/breakpoint trap.
0x000000000040123b in func_a ()
(gdb) where
#0 0x000000000040123b in func_a ()
Backtrace stopped: Cannot access memory at address 0xffffde57
(gdb)
This issue only occurs when I have more than one function in the array - with a single function it works fine, but multiple functions always causes a trap.
Looking at the disassembly, it appears that in the single case, clang
just inlines the call, which is why the issue only occurs with multiple elements in the array.
My question is: why is this happening, and is it a bug in my code, or in clang?
My System
$ uname -srvpio
Linux 6.9.3-76060903-generic #202405300957~1736980680~22.04~44ea8a9 SMP PREEMPT_DYNAMIC Thu J x86_64 x86_64 GNU/Linux
I can however reproduce this with on Compiler Explorer (see link below)
Code
Source
#include <stdio.h>
typedef void (Func)(void);
typedef struct { char *name; Func *ptr; } Function;
static void func_a(void) { printf("()"); }
static void func_b(void) { printf("()"); }
static void func_c(void) { printf("()"); }
static void func_d(void) { printf("()"); }
Function
function_a = { "a", &func_a },
function_b = { "b", &func_b },
function_c = { "c", &func_c },
function_d = { "d", &func_d };
Function *const functions[] = {
&function_a,
&function_b,
&function_c,
&function_d,
};
size_t functions_len = sizeof functions / sizeof *functions;
int main(void) {
size_t i;
setbuf(stdout, NULL);
for (i = 0; i < functions_len; i++) {
Function *const func = functions[i];
printf("%s", func->name);
func->ptr();
printf(";");
}
return 0;
}
Disassembly
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745248147a4618511.html
评论列表(0条)