2012-03-15 4 views
4

私は、ユーザーが入力したいときにHello、worldを何度も印刷するファイルを作成しました。c stack smashingが検出されました

#include <stdio.h> 
#include <string.h> 
int main() { 
    char message[10]; 
    int count, i; 

    strcpy(message, "Hello, world!"); 

    printf("Repeat how many times? "); 
    scanf("%d", &count); 

    for(i=0; i < count; i++) 
     printf("%3d - %s\n", i, message); 
} 

数字が何であっても、常に「スタック・スマッシュ」となります。ここにプログラムがあります、なぜ誰がこれをやっているのかという結論を出すことができますか?ここでは、スタックスマッシュの後に発生する「トレースバック」が検出されている:"Hello, world!"が10個の以上の文字であるため

[email protected]:~/programming$ ./a.out 
Repeat how many times? 12 
    0 - Hello, world! 
    1 - Hello, world! 
    2 - Hello, world! 
    3 - Hello, world! 
    4 - Hello, world! 
    5 - Hello, world! 
    6 - Hello, world! 
    7 - Hello, world! 
    8 - Hello, world! 
    9 - Hello, world! 
10 - Hello, world! 
11 - Hello, world! 
*** stack smashing detected ***: ./a.out terminated 
======= Backtrace: ========= 
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0x1f8c75] 
/lib/i386-linux-gnu/libc.so.6(+0xe8c27)[0x1f8c27] 
./a.out[0x8048524] 
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x129113] 
./a.out[0x80483f1] 
======= Memory map: ======== 
00110000-00288000 r-xp 00000000 08:01 1577912 /lib/i386-linux-gnu/libc-2.13.so 
00288000-0028a000 r--p 00178000 08:01 1577912 /lib/i386-linux-gnu/libc-2.13.so 
0028a000-0028b000 rw-p 0017a000 08:01 1577912 /lib/i386-linux-gnu/libc-2.13.so 
0028b000-0028e000 rw-p 00000000 00:00 0 
0036b000-0036c000 r-xp 00000000 00:00 0   [vdso] 
00454000-00470000 r-xp 00000000 08:01 1573818 /lib/i386-linux-gnu/libgcc_s.so.1 
00470000-00471000 r--p 0001b000 08:01 1573818 /lib/i386-linux-gnu/libgcc_s.so.1 
00471000-00472000 rw-p 0001c000 08:01 1573818 /lib/i386-linux-gnu/libgcc_s.so.1 
00e7e000-00e9c000 r-xp 00000000 08:01 1573924 /lib/i386-linux-gnu/ld-2.13.so 
00e9c000-00e9d000 r--p 0001d000 08:01 1573924 /lib/i386-linux-gnu/ld-2.13.so 
00e9d000-00e9e000 rw-p 0001e000 08:01 1573924 /lib/i386-linux-gnu/ld-2.13.so 
08048000-08049000 r-xp 00000000 00:14 3801591 /home/sean/programming/a.out 
08049000-0804a000 r--p 00000000 00:14 3801591 /home/sean/programming/a.out 
0804a000-0804b000 rw-p 00001000 00:14 3801591 /home/sean/programming/a.out 
08a9e000-08abf000 rw-p 00000000 00:00 0   [heap] 
b77e8000-b77e9000 rw-p 00000000 00:00 0 
b77fc000-b7800000 rw-p 00000000 00:00 0 
bff87000-bffa8000 rw-p 00000000 00:00 0   [stack] 
Aborted 
+4

使用しているコンパイラの警告を表示すると便利です。たとえば、-Wallでgccを使用した場合、警告:制御は非void関数の終わりに達し、__builtin___strcpy_chkへの呼び出しは常に宛先バッファをオーバーフローさせます。後者は問題の内容を明確にします。 – DSM

答えて

34

...

+10

インスタントクラシック – Ulterior

2

あなたmessage配列は、長い文字列よりも1文字以上にする必要があります暗黙的に'\0'ヌルターミネータを保持する必要があることに注意してください。

11

messageは、10バイトしか保持できません。文字列「Hello World!」をコピーしています。これは13バイト(ヌル文字をカウントする場合)になり、スタックプロテクターのクッキーを上書きして破損することになります。

クッキーは、戻りアドレスがスタック上で変更された場合にクラッシュするようにコンパイラによって挿入されるランダムなバイトで、潜在的なバッファオーバーフローの悪用を防ぎます。

gccでコンパイルする場合は、-fno-stack-protectorスイッチをコンパイルステートメントに追加してもう一度試してみてください。プログラムはおそらくクラッシュしますが(そのようなエラーメッセージはありません)、バッファオーバーフローの脆弱性が存在します。

+0

注:OPは "Hello、World!"を使用しました。 - 0ターミネータで14バイト。 – mattnz

+0

@mattnzああ、私はカンマを逃した。ねじ込め。いいんだよ。私はその投稿をもう一度編集するつもりはありません:) –

0

これまで説明したように、Hello World!長すぎます。

char message[]="Hello World!"; 

これは自動的に正しいサイズになります。

+4

あなたはそのことを再度確認したいかもしれません... –

+0

おっと...それは私が同時に多くのプログラミング言語を使用することで得られるものです... – PearsonArtPhoto

3

メッセージ配列は10文字(0-9)ですが、"Hello, World!"(引用符なし)とカウントすると13文字です。そのため、配列の一部ではないメモリを上書きします。

strcpy()strcat()その他のほとんどのC文字列関数は、配列の長さをチェックしません。十分なスペースを与えたと仮定します。

このように、メッセージアレイのスペースを増やす必要があります。しかし、どれくらい? 「こんにちは、世界!ヌルターミネーター文字'\0'にもう1つ追加すると、文字列の終わりが決まります。 14文字の配列を宣言する必要があります。

文字列とヌル文字を使用した作業の詳細については、this pageをお勧めします。それは(C++はCに基づいている)、CとC++の両方に共通であるもの

をカバーしてC++のページであるがPearsonartphotoが言ったようにまた、あなただけの

char message[] = "Hello, World!"; 

として、あなたの配列を宣言することができますしかし、これが学校やユニ授業のためのものであれば、このように教えられていることを確認してください。時には「先を急ぐ」ためのマークを差し引くことができます。この種の質問の考え方は、funementalsを教えることであり、特定のことがどのように働くのか、彼らは、最も簡単で効率的な方法ではないかもしれません(あなたが得ているスタックスマッシュのタイプは、今日の主要なシステムはプログラマがサイズの確認などを忘れるためです)。

-1

私はこの方法で構造体を定義したとき、私はこの問題を持っていた:

struct data { 
...variables... 
char text[]; 
}; 

は、これは何の警告を与えることが、私の場合にはエラーをスタックスマッシングを引き起こしたことはありません。 これを次のように置き換えました。

char text[100]; 
関連する問題