PHPの浮動小数点処理に無限ループのバグ 21
ストーリー by headless
ぐるぐる 部門より
ぐるぐる 部門より
あるAnonymous Coward 曰く、
PHPにて、浮動小数点数の変換処理の際に無限ループに陥り、サーバーをクラッシュさせるバグが発見された(本家/.、バグ発見者のブログ記事)。
影響するバージョンはPHP5.2および5.3。文字列"2.2250738585072011e-308"(304桁の10進数表記でも同様)からdoubleへの変換を、PHPの32ビットプロセス上で実行した場合にのみ再現されるとのことだ(ニュースリリース)。
このバグは3日に指摘され、4日にはPHP開発チームによりパッチがリリースされている。
処理時間 (スコア:2, 興味深い)
サーバクラッシュする前にmax_execution_timeのセットした時間で処理が強制的に終了させられると思うけど違うのか?
30秒以内にクラッシュさせれば良いんだよ (スコア:2)
Javaでも (スコア:2)
Java Hangs When Converting 2.2250738585072012e-308 - Exploring Binary [exploringbinary.com]
Re: (スコア:0)
PHP で製作されたサイトを守る方法 (スコア:1, おもしろおかしい)
PHP で製作されていることを知られないことが最重要らしいです。
Re: (スコア:0)
最重要とは書いてないけどね。
"In general, security by obscurity is one of the weakest forms of security. But in some cases, every little bit of extra security is desirable." [php.net]
Re: (スコア:0)
「Powered by なんたら」とコードに注入して自己主張/シェア拡大を狙うようなCMSを使うなってことですね。
作者の気持ちもわからんでもないけど。PHPに限らず、何のどのバージョンかがわかってしまうと既知の脆弱性情報からクラックしやすいってのはお約束。
とりあえずおやくそく (スコア:0)
Re:とりあえずおやくそく (スコア:1)
暗黒ループとかどうでしょう?
LIVE-GON(リベゴン)
リリースされたパッチ (スコア:0)
http://svn.php.net/viewvc/php/php-src/trunk/Zend/zend_strtod.c?r1=3070... [php.net]
変数に volatile を付け足すだけの修正で直ったらしいんだけど、どういう最適化が原因で無限ループになるの?
Re:リリースされたパッチ (スコア:1, 興味深い)
インテルマシン以外でも起きるのかなこれ? インテルマシンでだけ起きるなら、浮動小数点の内部表現形式が(IEEE754の64ビットじゃなくて)80bitであることが原因かも(volatileが付くとたぶんいちいち64ビットに直すコードになるはず)。
Re:リリースされたパッチ (スコア:1, 参考になる)
コミットログに "Fix bug #53632 with x87 fpu" とあるので80bit問題で正解でしょう。
10進小数表記→2進浮動小数点数へのoptimalな変換は、途中に二重丸めが生じると境界値で誤った数になってしまうので
精度を正確にコントロールする必要があります。
全部整数でやるのが安全なんですが、bignum計算がかなり多くなっちゃうんですよね…
Re: (スコア:0)
アンダーフローしたので0にしたかったのに、処理をミスったんでしょ。
ここ [sun.com]のIEEE754倍精度の正の最小正規数を見ると"2.2250738585072014e-308"だけど、
問題の"2.2250738585072011e-308"は最後の桁が3小さいからね。
Re:リリースされたパッチ (スコア:5, 参考になる)
正規化数から非正規化数への境界のところで起きてるっていうのはそのとおりだと思うけど。
> 文字列からdoubleへの変換で問題になるんだから80bitは関係ないと思う。
関係あるんですよそれが。今回の問題がまさにそれだったかはわからないけど。ちゃんと変換しようと思うと、10進表現を2進数表記に直した時の仮数部の最後の1ビットを決めるために、そこより下の方の桁も正確に求める必要があります(でないとどっちに丸めていいかわからない)。そのへんは該当コードからも参照されてるClingerのPLDI90のペーパー[1]で議論されてるんですが、真面目にやろうとすると無限精度多倍長整数演算が必要になるんですな。これは、計算の途中結果を丸めてしまうと、最後に仮数部の有効数字でも丸めるので二重丸めが生じるせいです。
で、無限多倍長演算は重いんで、なるべくdoubleの範囲で計算して、誤差がやばそうな場合に無限多倍長演算に切り替えるってことをやるんですが、演算誤差の上限を正確に評価しないとならないんで、仮数部のビット数に依存するんですわ。
もちろんそこまで気にしないでいいっていう用途はあります。libcのstrtodなどはナイーブなアルゴリズムだと思う。それだと、浮動小数点数の書き出し→読み込みを繰り返すと丸めによって次第に値がドリフトしてく可能性があるんですが、それが問題にならないことも多いでしょう。ただ、phpはClingerのペーパーを参照して自前で実装するくらい気合いを入れてるんで、真面目にやろうとしてたんだと思います。
[1] http://www.cesura17.net/~will/Professional/Research/Papers/howtoread.pdf [cesura17.net]
最近のサーバは情けないな (スコア:0)
Crayなら無限ループだってすぐ抜けてくれるのに。
Re:最近のサーバは情けないな (スコア:2, 参考になる)
>Crayなら無限ループだってすぐ抜けてくれるのに。
Crayだけではなく、いわゆるメインフレームマシンであれば、あるプロセスが
無限ループに入ったくらいではびくともしません。そのプロセスに対して
割り当てられるCPU時間とか、優先度とかをきっちり管理してますので。
メインフレームからUNIX系マシンを使うようになって、よく感じたのは、
このあたりです。南下ちょっとおかしな事すると、すぐにシステム全体に
影響するという。
Re:最近のサーバは情けないな (スコア:2)
無限ループと投入データが多かったための延伸のプロセスと区別して
アベンドとか可能なのですか??
UNIXも最近は物理CPUが増えたので無限ループプロセスが1個ぐらい出現しても
全体のCPU不足にはなかなかならないですね。
オンラインプロセスの無限ループor長時間化プロセスの発見が適当になっているとは
思いますが。
確かにオンラインのトラブルだとM/Fで長時間化系は聞かないかな...
ユーザがくそ重いリクエストを出して、「応答無いな」と繰り替えしリクエストを
出すようなトラブル(これも輻輳崩壊の一種かな)になるとか。
Re: (スコア:0)
Xorg にて radeon サーバが常に CPU 100% なんだけど、
ちょっと調べてもどうにかする方法がわからず。
でも 8 core な PC で使っているもんで、
Xorg が 100% なくらい全然オッケーということで放置してます…
計算機の高速化により問題が解決される例ということで(違
Re: (スコア:0)
それって無限ループじゃ無いと思うんだが
Re:最近のサーバは情けないな (スコア:1)
# 上のコメントは分かっててマジレスしてるんですよ…ね?
マイクロソフトジョーク? (スコア:0)
今度出たCrayのスーパーコンピュータはとても速い。無限ループを6秒で抜ける。
今度出たCrayのスーパーコンピュータはとても速い。haltを2回書かないと止まらない。