0
void print( char * str ){ printf("%s",str); }

void some_function(){
    ... Loads a file into `char * buffer` ...
    ... Stores the function print before `buffer` address ...
    ((void(*)(void))buffer();
}

このファイルには、「Hello World」と、いくつかの判読不能な文字が含まれています。バッファを実行すると、「HelloWorld」が出力されます。

私はあなたがこのようなポインタを実行できることを知っています:

void (*foo)(int) = &bar; // such that void bar(int)
(*foo)(123);

しかし、void(int)関数をその関数とパラメーターをメモリ内に持つvoid(void)関数として実行するのは、私にとっては初めてのことです。

このように実行できるように、関数がメモリ内でどのように見えるか(文字列がヌル文字で終了するなど)の標準はありますか?

4

1 に答える 1

2

しかし、void(int)関数をその関数とパラメーターをメモリ内に持つvoid(void)関数として実行するのは、私にとっては初めてのことです。

良い。これは未定義の動作であり、絶対に実行しないでください。一部の実装で機能する可能性がありますが、結果が保証されるわけではありません。

このように実行できるように、関数がメモリ内でどのように見えるか(文字列がヌル文字で終了するなど)の標準はありますか?

いいえ、ありません。より適切には、引数が関数に渡される方法の標準はありません-それは実装次第であり、異なるタイプの関数が互換性を持つような方法で実装される必要はありません。

しかし、この場合、プログラマーは関数がメモリー内でどのように見えるかについての知識を利用しており、メモリーにロードされてこの特定の実装で実行されたときに正しいことを行うようにファイルを準備しました。結局のところ、これはローダーが行うことです...プログラムをファイルからメモリに読み取り、実行します。このメソッドは、プログラムのバグを利用して不正なコードをプログラムのメモリにロードし、プログラムに実行させるエクスプロイトでも使用されます。

于 2012-09-27T02:58:43.613 に答える