Fix invalid function pointer cast in cpuinfo.c
While casting function pointers is allowed in C, the function must
ultimately be called through a pointer with the same type signature as
the function itself. Type signature mismatches, even decaying T* to
void* is undefined behavior.
UBSan flags this with -fsanitize=function. The easiest way I found to
repro this was:
CC=clang-18 CXX=clang++-18 \
CFLAGS="-fsanitize=function -fno-sanitize-recover=function" \
CXXFLAGS="-fsanitize=function -fno-sanitize-recover=function" \
cmake -GNinja -B build -DCPUINFO_BUILD_BENCHMARKS=OFF
ninja -C build
./build/cpu-info
That gives the following error:
[...]/src/linux/multiline.c:85:11: runtime error: call to function parse_line through pointer to incorrect function type 'bool (*)(const char *, const char *, void *, unsigned long)'
cpuinfo.c: note: parse_line defined here
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior [...]/src/linux/multiline.c:85:11
The fix is fairly straightforward: just keep the function at the type
signature the expected, and cast void* instead the function instead.
diff --git a/src/x86/linux/cpuinfo.c b/src/x86/linux/cpuinfo.c
index 7df72ab..8f038b0 100644
--- a/src/x86/linux/cpuinfo.c
+++ b/src/x86/linux/cpuinfo.c
@@ -83,8 +83,9 @@
static bool parse_line(
const char* line_start,
const char* line_end,
- struct proc_cpuinfo_parser_state state[restrict static 1],
+ void* context,
uint64_t line_number) {
+ struct proc_cpuinfo_parser_state* restrict state = context;
/* Empty line. Skip. */
if (line_start == line_end) {
return true;
@@ -215,5 +216,5 @@
.processors = processors,
};
return cpuinfo_linux_parse_multiline_file(
- "/proc/cpuinfo", BUFFER_SIZE, (cpuinfo_line_callback)parse_line, &state);
+ "/proc/cpuinfo", BUFFER_SIZE, parse_line, &state);
}