使用container_of时如何规避security.ArrayBound警告?
问题:使用container_of宏触发clang-tidy的security.ArrayBound警告
我编写了通过container_of宏从内部结构体指针获取父结构体指针的代码,但运行clang-tidy时触发了security.ArrayBound警告。
示例代码
#include <stdio.h> #include <stddef.h> #include <assert.h> #define container_of(ptr, type, member) ({ \ const void *__mptr = (void *)(ptr); \ (type *)((char *)__mptr - offsetof(type, member)); \ }) /* 简单内部结构体 */ struct inner_data { int id; float value; }; /* 包含内部结构体的容器结构体 */ struct container { double extra_value; char name[32]; int count; struct inner_data data; /* 嵌入式内部结构体 */ }; /* 操作内部结构体的函数 */ void update_data(struct inner_data *data, float new_value) { /* 使用container_of获取容器结构体指针 */ struct container *parent = container_of(data, struct container, data); /* 更新容器结构体字段 */ parent->extra_value = new_value * 2.0; } int main() { struct container my_container; struct inner_data * mydata = &my_container.data; update_data(mydata, 200.0); }
触发的警告信息
运行命令:clang-tidy-21 -checks=clang-analyzer-* test.c -- -std=c11 -O2
得到警告:
1 warning generated. /tmp/test.c:31:13: warning: Out of bound access to memory preceding 'my_container.data' [clang-analyzer-security.ArrayBound] 31 | parent->extra_value = new_value * 2.0; | ^ /tmp/test.c:38:5: note: Calling 'update_data' 38 | update_data(mydata, 200.0); | ^~~~~~~~~~~~~~~~~~~~~~~~~~ /tmp/test.c:31:13: note: Access of 'my_container.data' at negative byte offset -44 31 | parent->extra_value = new_value * 2.0; | ~~~~~~~~^~~~~~~~~~~
解决方法
这个警告属于clang静态分析器的误报,它无法识别container_of的合法指针偏移逻辑。可以通过以下几种方式处理:
1. 单位置抑制警告
在触发警告的代码行上方添加注释,让clang-tidy忽略该位置的特定警告:
void update_data(struct inner_data *data, float new_value) { struct container *parent = container_of(data, struct container, data); // NOLINTNEXTLINE(clang-analyzer-security.ArrayBound) parent->extra_value = new_value * 2.0; }
2. 优化container_of宏写法
给宏添加类型兼容性检查,帮助分析器识别这是合法操作,同时提升代码安全性:
#define container_of(ptr, type, member) ({ \ static_assert(__builtin_types_compatible_p(__typeof__(ptr), __typeof__(&((type *)0)->member)), \ "container_of: 指针类型不匹配"); \ const typeof(((type *)0)->member) *__mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); \ })
这里的static_assert会在编译期检查传入的指针类型是否和结构体成员的指针类型匹配,避免错误使用宏,同时让分析器更容易理解宏的逻辑。
3. 全局排除该警告(不推荐)
如果多个位置出现此类误报,可以在clang-tidy命令中排除该检查:
clang-tidy-21 -checks=clang-analyzer-*,-clang-analyzer-security.ArrayBound test.c -- -std=c11 -O2
注意:这种方式会忽略所有security.ArrayBound类型的警告,可能错过真正的数组越界问题,仅在确认所有相关警告都是误报时使用。
内容的提问来源于stack exchange,提问作者shodanex
相关产品推荐
相关产品推荐

