0

我们有一个非常大的 C++ 代码库,我们希望使用带有“FORTIFY_SOURCE=2”选项的 gcc 进行编译,以提高安全性并降低缓冲区溢出的风险。问题是当我们使用 FORTIFY_SOURCE 编译系统时,二进制大小急剧增加。(从总共 4GB 到超过 25GB)当我们需要部署代码时,这会导致问题,因为压缩和部署它需要 5 倍的时间。

为了弄清楚发生了什么,我制作了一个简单的测试程序,它使用strcpy(其中一个函数 FORTIFY_SOURCE 应该在使用和不使用“FORTIFY_SOURCE”的情况下增强和编译它)执行一堆字符串副本。

#include <cstring>
#include <iostream>

using namespace std;

int main()
{
    char buf1[100];
    char buf2[100];
    char buf3[100];
    char buf4[100];
    char buf5[100];
    char buf6[100];
    char buf7[100];
    char buf8[100];
    char buf9[100];
    char buf10[100];

    strcpy(buf1, "this is a string");
    strcpy(buf2, "this is a string");
    strcpy(buf3, "this is a string");
    strcpy(buf4, "this is a string");
    strcpy(buf5, "this is a string");
    strcpy(buf6, "this is a string");
    strcpy(buf7, "this is a string");
    strcpy(buf8, "this is a string");
    strcpy(buf9, "this is a string");
    strcpy(buf10, "this is a string");
}

汇编:

g++ -o main -O3 fortify_test.cpp

g++ -o main -D_FORTIFY_SOURCE=2 -O3 fortify_test.cpp

我发现在一个简单的示例中使用“FORTIFY_SOURCE”对二进制大小没有明显影响(生成的二进制文件是 8.4K,有和没有加强源。)

当一个简单的例子没有明显的影响时,我不希望在更复杂的例子中看到如此急剧的大小增加。FORTIFY_SOURCE 可能会做些什么来大幅增加我们的二进制大小?

4

1 回答 1

0

您的示例实际上不是一个很好的示例,因为上面没有可强化的代码。代码强化并不神奇,编译器只能在某些特定条件下才能做到。

让我们以 2 个函数的代码为例,一个可以由编译器强化(因为从代码本身可以确定缓冲区的最大大小),另一个不能(因为缺少相同的信息):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>

int f_protected(char *in)
{
    char buffer[256];     
    memcpy(buffer, in, strlen(in));
    printf("Hello %s !\n", buffer);
    return 0;
}

int f_not_protected(char *in, int sz)
{
    char buffer[sz];
    memcpy(buffer, in, strlen(in));
    printf("Hello %s !\n", buffer);
    return 0;
}

int main (int argc, char **argv, char **envp)
{
    if(argc < 2){
        printf("Usage: %s <some string>\n", argv[0]);
        exit(EXIT_SUCCESS);
    }
    
    f_protected(argv[1]);
    f_not_protected(argv[1], strlen(argv[1]));
    return 0;
}

有一个很棒的在线工具可以让你在https://godbolt.org/上比较编译的代码

您实际上可以在此处比较此示例的两个编译版本

正如您将在 ASM 输出中看到的那样,该函数的强化版本确实比未强化的版本执行更多检查,需要额外的 ASM 代码,实际上增加了文件大小。

但是,很难想到会大幅增加代码大小的情况。是否有可能您没有剥离调试信息?

于 2021-09-14T14:35:46.007 回答