3

これは、いくつかのものをテストした後に書いたcコードの一部です。

これが脆弱性の問題ではないことはわかっていますが、プログラムが正常に戻った後、プロンプトが stdin、stdout、stderr に戻った時点で stdin がフラッシュされない理由がわかりません。プログラムの通常の実行が終了した後、標準入力の残りの文字が標準出力にリダイレクトされ、フラッシュされないのはなぜですか?

$cat dummy.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

int main(){

    char rbuf[100];

        if (read(0, rbuf,5) == -1){
        perror("learn to count");
        printf("errno = %d.\n", errno);
        exit(1);
    }
        //printf("rbuf : %s\n",rbuf);
    return 1;   
}

ここで実行:

$ gcc -o dummy dummy.c
$ ./dummy 
AAAAA /bin/sh
$  /bin/sh
sh-3.2$ exit
exit
$

これは、プロンプトである mew stdout に出力された stdin の残りの文字列にすぎないと思います。最後に改行を追加すると、ユーザーがコマンドを実行するために押したエンターを何らかの方法でエミュレートします。どうしたの?私はそれについてもっと知りたいと思っています。

4

2 に答える 2

2

はい、あなたの推測は正しいです。これらは の余分な文字ですstdin:

これを行う:

void flush_stdin()
{
   while(getchar() != '\n');
}

注: onは未定義の動作であるため使用fflush()しないでくださいstdin

編集

は、プログラムを開始する端末( stdin) に配線されていますbash。これにより、新しいプログラムが開始されdummystdinofがofdummyに接続されます。stdinbash

それ以降、dummyプロセスは 5 文字を処理し、他の文字は無視します (バッファreadに残します)。stdinコントロールが に戻るとbashbuffer. ほら、stdinバッファに文字があるため、プログラムは待機する代わりにから読み取りを開始しstdinstdin最後に\nプロセスが実際に実行されるため、含まれています。これが始まり/bin/shます。残りは/bin/sh心配するまでです!

于 2013-02-15T15:08:51.427 に答える
0

プログラムを実行するために、シェルは fork(2) を呼び出して子プロセスを作成し、子プロセスで exec(3) を呼び出して自分自身を「ダミー」プログラムに置き換えます。

シェルのソースコードには次のようなものがあると思います(Cで書かれている場合):

if (fork() == 0)
    execlp(program, arguments)

子プロセスは、親のファイル記述子を継承します。この場合はシェルです。したがって、子プロセスには、それを実行したシェルと同じ stdin/stdout があり、これが仮想端末です。

正確な方法はわかりませんが、子プロセスの実行中に親プロセス(コマンドを入力した元のシェル)がstdinを何らかの形で無視すると思います。

プログラムが終了すると、シェルは標準入力を取り戻します。プログラムによって読み取られなかった余分な文字は、シェルに送られます。そしてもちろん、シェルはそれらをコマンドとして扱います。

最初に read(2) の代わりに fgetc(3) を使用しようとすると、余分な文字が失われ、シェルに送信されないように見えます...しかし、stdin のバッファを解除すると、fgetc(2) を使用して同じ効果が得られます。つまり、余分な文字はシェルに戻ります。

char rbuf[100];
setbuf(stdin, NULL); // with this line - same effect as using read(2)
                     // without it - extra characters are lost
for (int i = 0; i < 5; ++i)
    rbuf[i] = (char)fgetc(stdin);

デフォルトでは、stdin は行バッファリングされます。行全体が読み取られ、余分な文字が破棄されるため、バッファリングされた標準入力を使用すると、この動作が回避されるように見えますが、バッファリングされていない標準入力 (または低レベルの読み取り) は行の終わりまで読み取られず、余分な文字はそのまま残ります。プログラムが終了すると、親 (シェル) によって読み取られます。

于 2013-02-15T15:41:43.050 に答える