hnwの日記

PHPとRubyとPythonのparserをいじめてみた

下記のようなプログラムを与えると、PHPのparserが「無理っす」と言って死にます。

<?php
!!!…(10000個くらい)…!!!true;
$ php ./hoge.php
PHP Parse error:  memory exhausted in /Users/hanawa/hoge.php on line 2

yaccによるparserはシフトと還元を繰り返しながら構文解析していきます。単項演算子について言えば、後置された表現が確定するまで還元できませんから、!が連続している間はシフトし続け、トークンをスタックに積み続ける必要があります。

このようにトークンを記録するためのスタックのサイズがPHPでは10000個しかありません。ですから、単項演算子を10000個ほど書くだけで簡単に死にます。他にも、「(」を10000個ほど連続して置くなどの嫌がらせでもPHPを死なせることができます。

実装の手抜きといえば手抜きですが、実用上は大した問題ではないでしょう。

ちなみに、RubyPythonも同じ理由で同じように死にます。

#!/usr/bin/ruby
!!!…(10000個くらい)…!!!true;
$ ./hoge.rb
hoge.rb:2: memory exhausted
#!/usr/bin/python
not not not …(10000個くらい)… not not not True;
$ ./hoge.py
s_push: parser stack overflow
MemoryError

でも、CとPerlは同じことをしても死にませんでした。すげえぜPerl