You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何_FORTIFY_SOURCE在生成的二进制文件中无效果?

_FORTIFY_SOURCE在C++项目中未生效的问题排查

我在C++项目中尝试启用_FORTIFY_SOURCE以添加缓冲区溢出防护,但编译后分析二进制文件发现该防护并未生效:用checksec检查,或通过readelf -sW myprogram | grep __chk查找加固函数,均未发现任何__chk开头的加固函数。除Fortify外,其他编译标志的效果均符合checksec的预期输出。

我准备了一个最小可验证示例(MVCE),其中用到了memcpy和memmove这类本应被加固的函数,编译配置位于项目的cmake/compiler_settings.cmake文件中。

我尝试过修改该cmake配置文件,调整不同的优化级别(-O2、-O3)和_FORTIFY_SOURCE的值(2、3),编译步骤如下:

$ mkdir build && cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ cmake --build . --target all --config Release --

每次checksec的结果都一致:

$ checksec --fortify-file=./sources/Example/Stoppable_Example
* FORTIFY_SOURCE support available (libc)    : Yes
* Binary compiled with FORTIFY_SOURCE support: No

 ------ EXECUTABLE-FILE ------- . -------- LIBC --------
 Fortifiable library functions | Checked function names
 -------------------------------------------------------
 memcpy                         | __memcpy_chk
 memmove                        | __memmove_chk

SUMMARY:

* Number of checked functions in libc                : 83
* Total number of library functions in the executable: 270
* Number of Fortifiable functions in the executable : 2
* Number of checked functions in the executable      : 0
* Number of unchecked functions in the executable    : 2

排查与解决思路

1. 确认编译选项的正确传递

_FORTIFY_SOURCE生效必须满足两个核心条件:

  • 开启O1及以上优化级别(常用-O2/-O3)
  • 在预处理阶段定义_FORTIFY_SOURCE(通常设为2或3)

检查cmake配置:

  • 确保CMAKE_CXX_FLAGS_RELEASE中包含-O2 -D_FORTIFY_SOURCE=2
  • 禁止在Debug模式下测试(Debug默认优化级别为O0,会直接禁用Fortify)

2. 检查宏定义的时机

_FORTIFY_SOURCE必须在包含任何标准库头文件之前定义,否则编译器不会替换标准函数为加固版本。优先通过编译选项-D_FORTIFY_SOURCE=2传递宏定义(比add_definitions更可靠,避免头文件顺序问题)。

3. 验证编译器与libc兼容性

  • 确保GCC版本≥4.1(_FORTIFY_SOURCE最早引入版本),Clang版本≥3.0
  • 系统libc需支持该特性(如glibc≥2.4,checksec已显示libc支持,此步可快速排查)

4. 构造无法被优化的测试场景

如果编译器能确定内存操作边界绝对安全,会直接将memcpy/memmove替换为内联指令,此时__memcpy_chk不会出现在符号表中。可手动构造编译器无法确定边界的场景测试:

#include <cstring>

void test(char* dest, const char* src, size_t len) {
    memcpy(dest, src, len); // 编译器无法确定dest的大小,应触发__memcpy_chk
}

int main() {
    char buf[10];
    test(buf, "abcdefghijklmn", 15);
    return 0;
}

编译后用readelf检查是否存在__memcpy_chk符号。

5. 排查CMake配置覆盖问题

  • 确认未通过CMAKE_CXX_FLAGS而非CMAKE_CXX_FLAGS_RELEASE设置选项,导致Release模式下不生效
  • 检查第三方库的cmake脚本是否强制覆盖了优化级别或宏定义

内容的提问来源于stack exchange,提问作者user29745238

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:25:08