c - False positives with Clang CFI sanitizer and array of functions - Stack Overflow

This is a follow-up related to Inconsistent false positives with Clang CFI sanitizer and function point

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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信