我正在使用a library在编译时注册一些结构。在这种情况下,它正在注册一个表示我想公开的JSON-RPC方法的结构。该库用__attribute(section("xautodata_" "somename"))
标记结构,以便将其放在一个单独的节中,以供以后检索。生成的内容将如下所示:
static const autodata_json_command_ *__attribute__((__used__)) __attribute__((section("xautodata_" "json_command"))) autodata_json_command_151 = (&help_command);;
static const autodata_json_command_ *__attribute__((__used__)) __attribute__((section("xautodata_" "json_command"))) autodata_json_command_173 = (&stop_command);;
稍后检索命令的代码将获得指向该部分的指针(并计算该部分中的元素数量)并对其进行迭代,如下所示:
size_t count;
struct json_command **commands = get_json_commands(&count);
for (size_t i=0; i<count; i++) {
// Access commands[i];
}
如果我们不使用-fsanitize=address
进行编译,则可以很好地工作,但是使用-fsanitize=address
进行编译时,它将添加填充。
在没有地址清除器命令的情况下,彼此相邻,即commands[0]
和commands[1]
是指向结构的有效指针。使用消毒剂时,只有第8个命令才是有效的指针(大概是由于填充)。
现在是一个真正的问题:解决此问题的最干净方法是什么?我是否应该尝试增大步进大小(在这种情况下,需要预处理指令来区分消毒剂的用途)?还是有一种方法可以对本节中的内容禁用此填充?
答案 0 :(得分:1)
GCC Asan出于您概述的原因(即保持连续性)故意避免在自定义部分中插入变量:
/* Don't protect if using user section, often vars placed
into user section from multiple TUs are then assumed
to be an array of such vars, putting padding in there
breaks this assumption. */
|| (DECL_SECTION_NAME (decl) != NULL
&& !symtab_node::get (decl)->implicit_section
&& !section_sanitized_p (DECL_SECTION_NAME (decl)))
(来自gcc/asan.c)。在这种情况下,可以使用特殊标志-fsanitize-sections=wildcard1,wildcard2,...
强制执行检测。
另一方面,Clang Asan会忽略用户部分注释(请参见AddressSanitizer.cpp)。
我建议在Asan tracker上添加PR,以使Clang表现得像GCC一样,或者添加特殊标志来控制用户部分的配置(在后一种情况下,我们还需要更新Asan Clang/GCC incompatibility wiki)。 / p>