まず、ユーザーに文字列を出力してから入力を受け入れる小さなプログラムがあります。代わりに、ポートで送受信する方法でプログラムを操作したいと思います。これを試して達成するためにコマンドを実行しましたsocat TCP4-LISTEN:1337,reuseaddr,fork EXEC:./program
。このコマンドを使用してnc 127.0.0.1 1337
プログラムを実行して期待できるようにしたいです。
- プログラムからメッセージを受信する
- 入力を提供できる
- 切断
ところで、これを利用してプログラムを実行すると、socat
次のようになります。
- コメントを提示する
- プログラムから受信したメッセージ
- 他の入力を提供
- 切断
なぜこれが起こるのかわかりません。このコマンドの使用に問題がありますかsocat
?もしそうなら、何が欠けているか間違っているのか教えてください。
これが手順です。
#include <stdio.h>
void vuln(void) {
printf("Input\n");
char buffer[256];
gets(buffer); // potential buffer overflow
}
int main(void) {
vuln();
return 0;
}
答え1
Cでは、printf
バッファリングされたI / Oライブラリの一部です。ストリームに書き込まれたデータはメモリに「バッファリング」されます(つまり、カーネルに直接書き込まれません)。
デフォルトではstdout
(データが書き込まれるストリームprintf
)ラインバッファストリーミングは、改行がストリームに書き込まれるまで(またはフラッシュをトリガーする他の状況)、バイトがメモリバッファに格納されることを意味します。
標準出力が端末に関連付けられていないstdout
場合ブロックバッファストリーミングとは、バッファがいっぱいになるまでバイトがメモリバッファに格納されることを意味します。
端末でプログラムを実行すると、以下を呼び出してフラッシュがトリガされ'\n'
ますprintf
(ラインバッファリングされるため)。
$ ./a.out
Input
whatever-you-type
$
出力をファイルにリダイレクトすると、別の動作が表示されます。
Terminal 1 Terminal 2
-------------------- --------------------
$ ./a.out > /tmp/out
$ cat /tmp/out
$
type-input
$
$ cat /tmp/out
Input
$
socat
なしで実行すると、pts
出力ストリームはブロックバッファモードになり、出力ストリームと一緒に実行するとpts
ラインバッファモードになります。
この動作をオーバーライドする場合は、いくつかのオプションがあります。バッファリングされたデータを明示的にフラッシュする関数を呼び出すことができます。
printf("Input\n");
fflush(stdout);
または、次を呼び出す前に出力ストリームのバッファリングモードを明示的に設定できますprintf
。
setvbuf(stdout, NULL, _IONBF, 0); // _IONBF = Unbuffered
printf("Input\n");
Robert Loveの第3章を参照してください。Linuxシステムプログラミングより詳細な説明が必要です。