このコードを実行して、scanf
の入力として "Hello"(3文字以上)を入力すると、配列str
はオーバーフローしません。これは私には少し奇妙に聞こえますが、もちろん私は何かが欠けています。誰もがここで何が問題なのか分かっていますか?どうもありがとう!配列がオーバーフローしない(C言語)
char str[3];
scanf("%s", str);
printf("%s\n", str);
このコードを実行して、scanf
の入力として "Hello"(3文字以上)を入力すると、配列str
はオーバーフローしません。これは私には少し奇妙に聞こえますが、もちろん私は何かが欠けています。誰もがここで何が問題なのか分かっていますか?どうもありがとう!配列がオーバーフローしない(C言語)
char str[3];
scanf("%s", str);
printf("%s\n", str);
私はあなたのコードを実行しようとした、そしてそれはありませんセグメンテーション違反:
./main
ofejnhofewnhouwnofwbeqofenoifwenofwenoubwuiowgebouwegfougewfnbnbboue
ofejnhofewnhouwnofwbeqofenoifwenofwenoubwuiowgebouwegfougewfnbnbboue
Segmentation fault (core dumped)
私はあなたがscanf()
に合格しようとしているどのように多くの文字を知らないが、あなたが知っている必要があり、時々コンパイラこと保存されたESP/EIPと初期変数の間にパディングを実行します。
特に、ここでは、スタックに3バイトのメモリ領域を作成しています。コンパイラは最初に4に丸めます(x64では8)。しかしそれでも、それはより多くのスペースを追加するかもしれません。 gdb
で
、disass main
は私を与える:
0x000000000040057d <+0>: push %rbp
0x000000000040057e <+1>: mov %rsp,%rbp
0x0000000000400581 <+4>: sub $0x20,%rsp
sub 0x20
は32バイトで、明らかな方法より3バイトです。
厳密な "ダミー" Cのアセンブラディレクティブは期待しないでください。コンパイラは、意識しているよりも多くの最適化と意思決定を行います。
;-)
入手しました。ありがとうございました :) –
Cランタイムは発行しません...あなたのバッファとEIP間のバイトの正確な範囲は、通常、ブルートフォースを実行するために必要ですが、巧妙なハッカーがより興味深いアプローチを見つけるかもしれない発見しようとすると、エラー/警告メッセージが表示されますが、誤った結果が表示されます。 オーバーフロー/アンダーフローをチェックするには、あなたの責任で行ってください。
あなたは "配列str
はオーバーフローしません"と言ったが、どのように知っていますか?オーバーフローがどのように現れると思いますか?
実際、配列は、がオーバーフローしました。あなたはちょうど「幸運」を得て、(目に見える)反響はなかった。
コンピュータプログラミングについて理解するのは難しいことの1つは、ルールの適用がかなり矛盾している可能性があることです。交差点の信号が「歩いてはいけない」と言われても、車は来ないので、通りを横切ると、すぐに警官が現れておらず、あなたに尋ねると、あなたはどんなに驚いていますか?ジャイウォークのチケット?それは基本的にここで起こったことです。
あなたの配列の境界を上書きすることは[未定義の動作](https://stackoverflow.com/documentation/c/364/undefined-behavior/2144/accessing-memory-beyond-allocated-chunk)です。 「オーバーフローしない」というのは、「セグフォルトなしで印刷する」という意味で、今回はラッキーです。 "Hello"は 'str'に収まらないので、あふれてしまいます。あなたがすべてのことがうまくいっていると思うので、本当に_unlucky_です。 – yano
実際には関係はありませんが、2つ以上の文字を入力するとubが呼び出されることに注意してください。この種のエラーをキャッチするために使用できるランタイムツールがいくつかありますが、警告フラグはこれをキャッチしませんが、初期化されていない変数を読み込もうとするなど、他のub呼び出しコードをキャッチするためには便利です。 – George
それは私の心に来るすべての文字列を入力しようとしているので、実際には本当に奇妙で、エラーは表示されません。たぶんそれは自動的にそのすべてを処理する "最新の"コンパイラです。私はちょうどMac上のターミナルを使ってコンパイルし、 "gcc -o fs main.c"と入力して実行しています。 –