[C/C++] バッファオーバーフロー対策 -fstack-protector-all

[M1 Mac, Big Sur 11.6.8, clang 13.0.0, NO IDE]

前回までscanf関数におけるバッファオーバーフローについて検証してきました。

コンパイラの対策としてgcc, g++, clang++などにはバッファオーバーフロー検知のメカニズムが実装されていて、未然に処置を施す仕組みになっています。

この機能はコンパイル時に-fstack-protector-allオプションを付加すると有効になります。

LLDBでその挙動を確認したところ、オーバーフローが発生しそうなchar変数をより上位アドレスに配置し、本来なら隣接するはずの別変数との位置関係が逆転してさらにその間に10バイトの空白アドレスが配置されました。

気をつけないといけないのはプログラムにてprintfなどでこれらの変数のメモリアドレスを出力させるとこの機能が無効になってしまう点です。

#include <cppstd.h>

int main() {
    int i;
    char c;

    for (i=0;i<5;i++){
        printf("for文先頭直後 printf i: %d\n",i);
        // rewind(stdin); // ストリームバッファをクリア
        scanf("%s", &c);

        cout << "cout c: " << c << endl;
        printf("printf c: %s\n",&c);

        printf("printf i: %d\n",i);
       
    }
    return 0;
--------------------------------------------------
出力
--------------------------------------------------
for文先頭直後 printf i: 0
a
cout c: a
printf c: a
printf i: 0
for文先頭直後 printf i: 1
a
cout c: a
printf c: a
printf i: 1
for文先頭直後 printf i: 2
(lldb) print &i
(int *) $1 = 0x000000016fdff57c
(lldb) print &c
(char *) $2 = 0x000000016fdff587 "a"