1

このマクロは安全ですか、それともallocaがNULLを返さないようにする必要がありますか?

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

1 に答える 1

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)からの戻り値を減算する前に、クイックアライメント以外に健全性チェックがないことに注意してください。

于 2012-10-18T07:21:02.613 に答える