C でバッファ オーバーフローを実験していたところ、興味深い癖が見つかりました。
任意の配列サイズに対して、SIGABRT がクラッシュする前にメモリに書き込むことができるオーバーフロー バイト数が設定されているようです。たとえば、以下のコードでは、10 バイトの配列が 27 でクラッシュする前に 26 バイトにオーバーフローするchar
可能性がありますchar
。
これがなぜなのか説明できる人はいますか?また、SIGABRT は「セグメンテーション違反」と同じ (または原因) ですか?
Mac OS 10.8 - Xcode 4.6、clang および lldb。ありがとう!
#include <stdio.h>
int main(int argc, const char * argv[])
{
char aString[ 10 ];
char aLetter = 'a';
printf("The size of one array slot sizeof( aString[0] ) is %zu\n", sizeof(aString[0]));
printf("The size of one letter sizeof( aLetter ) is %zu\n", sizeof(aLetter));
// Overflow the aString array of chars
// lldb claims aString is initialized with values \0 or NULL at all locations
// Substitute i<27 and this code will crash regularly
for (int i=0; i<26; i++) {
aString[i]= aLetter;
}
return 0;
}
編集 - 逆アセンブルでステップスルーし、for ループの直後にこの保護を見つけました:
0x100000f27: movq 226(%rip), %rax ; (void *)0x00007fff793f24b0: __stack_chk_guard
0x100000f2e: movq (%rax), %rax
0x100000f31: movq -8(%rbp), %rcx
0x100000f35: cmpq %rcx, %rax
0x100000f38: jne 0x100000f49 ; main + 121 at main.c:26
.
.
.
0x100000f49: callq 0x100000f4e ; symbol stub for: __stack_chk_fail