それSP戻せばできるよ(仮)
shinhさんの「ふとイヤなコードを思いつきました」にインスパイヤされてみました。
...といいたいところなのですがあまりよいものはできず。
// なかなかポータブルなハローワールド main() { char _[0x40000000]; char __[0x40000000]; char ___[0x40000000]; char ____[0x3fffff60]; char _____[0x00000091]; return puts(*(char**)_____ + 2); }
環境及び実行結果:
% uname -a Linux localhost.localdomain 2.6.17-1.2174_FC5 #1 Tue Aug 8 15:30:55 EDT 2006 i686 athlon i386 GNU/Linux % gcc -v Target: i386-redhat-linux gcc version 4.1.1 20060525 (Red Hat 4.1.1-1) % gcc hello.c -o 'hello world!' % ./hello\ world\! hello world! %
まず、引数ナシまたは2引数で呼ぶというネタが一部で確立している気がするputs関数を普通に1引数で呼んでいる時点で敗北しています。最後のサイズ0x91な変数をとっぱらえば引数ナシで呼べそうなものなんですが、自動変数の合計サイズが1GB(多分)をこえていると、gcc様が "error: total size of local objects too large" という見慣れない文句をつけてくるので、ダミーの変数を置き合計サイズが4GBを超えるようにして(size_tな値がwrap aroundするようにして)やらないとだめなのでした。
配列____[]を直接argv[0]の指し先に重ねてしまう方法もありますが、それだとスタック開始位置のランダム化を切らないとだめなんで、とりあえずargv[0]そのものを使うようにしてみたのは多少工夫した点ではあります(がちょっとなー)。なお上記コード、x86_64なgcc-4.1.1でgcc -m32でコンパイルしたらICEしました。なんで。
うーん。内容には関係ありませんが、シゴトで消防士に任命されて焼け死にそうな為、即座にテキトーな事を書けないのも無念。