这个宏对于复制字符串是否安全?

时间:2012-10-18 02:55:36

标签: c

这个宏是安全的还是我应该确保alloca永远不会返回NULL?

#define DO_COPY(x) strcpy(alloca(strlen((x)) + 1), x)

1 个答案:

答案 0 :(得分:2)

如果字符串是用户控制的,我会说alloca不安全。在许多编译器中实现alloca的方式,它不会对它从中减去的数量(或者如果你的堆栈增长那么增加)堆栈指针进行任何形式的完整性检查。即使堆栈周围有大的红色区域,也可以相对容易地将alloca():ed字符串指向堆栈外部。

特别是在线程环境中,线程堆栈可以非常小并且彼此靠近。

在Linux机器上,我可以测试它,它需要一个10MB的字符串来开始在其他一些线程堆栈上涂鸦。在MacOS上512kB似乎已经足够了。

这是一个快速的黑客,你可以看到你的结果有多接近(请注意,如果堆栈分配是使用一些随机分配器完成的,如OpenBSD或其他系统认真对待其分配器安全性)

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>

void *
x(void *v)
{
    int x;

    return &x;
}

int
main(int argc, char **argv)
{
    pthread_t ta, tb;
    char *va, *vb;

    pthread_create(&ta, NULL, x, NULL);
    pthread_create(&tb, NULL, x, NULL);

    pthread_join(ta, (void **)&va);
    pthread_join(tb, (void **)&vb);

    printf("diff: %d\n", abs((intptr_t)vb-(intptr_t)va));

    return 0;
}

以下是strcpy(alloca(strlen(s)+ 1),s)被编译为:

    movq    %rbx, %rdi
    call    _strlen
    addq    $31, %rax
    andq    $-16, %rax
    subq    %rax, %rsp
    movq    %rsp, %rdi
    movq    %rbx, %rsi
    call    _strcpy

注意除了快速对齐之外没有健全性检查,然后从堆栈指针中减去strlen(%rax)中的返回值。