Uniciesで
、またはどこか他のあなたはexecve
持っており、それがthe man page specifiesのように動作し、あなただけ... は、atoi
を使用するための私を殺すことができます。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** argv) {
(void) argc;
printf("arg: %s\n", argv[1]);
int count = atoi(argv[1]);
if (getchar() == 'y') {
++count;
char buf[20];
sprintf(buf, "%d", count);
char* newargv[3];
newargv[0] = argv[0];
newargv[1] = buf;
newargv[2] = NULL;
execve(argv[0], newargv, NULL);
}
return count;
}
例:
$ ./res 1
arg: 1
y
arg: 2
y
arg: 3
y
arg: 4
y
arg: 5
y
arg: 6
y
arg: 7
n
7 | $
(7戻りコードでした)。
再帰的にも明示的にループすることなく、自分自身を呼び出すだけで、自身のメモリ空間を新しいバージョンのものに置き換えます。
このようにして、スタックは再オーバーフローすることはありません。以前のすべての変数は再呼び出しと同様に再宣言されますが、getchar
呼び出しは100%CPU使用率を防ぎます。
自己更新バイナリの場合、実行時にバイナリ全体(少なくともUNIXについてはわかりません)がメモリにコピーされるため、ファイルがディスク上で変更されるとexecve(argv[0], ...
コールの前に、同じ古いものではなく、ディスク上に見つかった新しいバイナリが代わりに実行されます。
として@CarstenSとによりUnixのは、オープン・ファイル記述子がfork
/exec
渡って保持されているように設計されたユニークな方法に、コメントで指摘@bishop、および全体でオープンファイルディスクリプタを漏洩しないようにするために、結果として、 execve
に電話する場合は、execve
より前に閉じるか、e
,FD_CLOEXEC
/O_CLOEXEC
で開きます。詳細はDan Walsh's blogで確認できます。
出典
2016-10-13 17:44:27
cat
あなたがしていることは、あなたのコードで 'main()'を呼ばないでください。 – NathanOliver
"すべての変数を手動で再起動する" Wut? – Treycos
ループを使用することを検討しましたか? –