パスワードを忘れた? アカウント作成
288626 story
PHP

PHPの浮動小数点処理に無限ループのバグ 21

ストーリー by headless
ぐるぐる 部門より

あるAnonymous Coward 曰く、

PHPにて、浮動小数点数の変換処理の際に無限ループに陥り、サーバーをクラッシュさせるバグが発見された(本家/.バグ発見者のブログ記事)。

影響するバージョンはPHP5.2および5.3。文字列"2.2250738585072011e-308"(304桁の10進数表記でも同様)からdoubleへの変換を、PHPの32ビットプロセス上で実行した場合にのみ再現されるとのことだ(ニュースリリース)。

このバグは3日に指摘され、4日にはPHP開発チームによりパッチがリリースされている。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • 処理時間 (スコア:2, 興味深い)

    by Anonymous Coward on 2011年01月09日 14時29分 (#1885515)

    サーバクラッシュする前にmax_execution_timeのセットした時間で処理が強制的に終了させられると思うけど違うのか?

  • by 5963 (15563) on 2011年02月07日 2時00分 (#1899389)
    同じ問題があるそうですね。
    Java Hangs When Converting 2.2250738585072012e-308 - Exploring Binary [exploringbinary.com]
  • by Anonymous Coward on 2011年01月09日 14時38分 (#1885519)

    PHP で製作されていることを知られないことが最重要らしいです。

  • by Anonymous Coward on 2011年01月09日 15時59分 (#1885548)
    無限ループってこわくね?
  • by Anonymous Coward on 2011年01月09日 16時02分 (#1885551)

    http://svn.php.net/viewvc/php/php-src/trunk/Zend/zend_strtod.c?r1=3070... [php.net]

    変数に volatile を付け足すだけの修正で直ったらしいんだけど、どういう最適化が原因で無限ループになるの?

    • by Anonymous Coward on 2011年01月09日 16時09分 (#1885554)

      インテルマシン以外でも起きるのかなこれ? インテルマシンでだけ起きるなら、浮動小数点の内部表現形式が(IEEE754の64ビットじゃなくて)80bitであることが原因かも(volatileが付くとたぶんいちいち64ビットに直すコードになるはず)。

      親コメント
      • by Anonymous Coward on 2011年01月09日 16時40分 (#1885568)

        コミットログに "Fix bug #53632 with x87 fpu" とあるので80bit問題で正解でしょう。
        10進小数表記→2進浮動小数点数へのoptimalな変換は、途中に二重丸めが生じると境界値で誤った数になってしまうので
        精度を正確にコントロールする必要があります。
        全部整数でやるのが安全なんですが、bignum計算がかなり多くなっちゃうんですよね…

        親コメント
      • by Anonymous Coward
        文字列からdoubleへの変換で問題になるんだから80bitは関係ないと思う。

        アンダーフローしたので0にしたかったのに、処理をミスったんでしょ。

        ここ [sun.com]のIEEE754倍精度の正の最小正規数を見ると"2.2250738585072014e-308"だけど、
        問題の"2.2250738585072011e-308"は最後の桁が3小さいからね。
        • by Anonymous Coward on 2011年01月09日 18時15分 (#1885609)

          正規化数から非正規化数への境界のところで起きてるっていうのはそのとおりだと思うけど。

          > 文字列から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]

          親コメント
  • by Anonymous Coward on 2011年01月09日 18時39分 (#1885620)

    Crayなら無限ループだってすぐ抜けてくれるのに。

    • by ribbon (11750) on 2011年01月09日 22時00分 (#1885670) 日記

      >Crayなら無限ループだってすぐ抜けてくれるのに。

      Crayだけではなく、いわゆるメインフレームマシンであれば、あるプロセスが
      無限ループに入ったくらいではびくともしません。そのプロセスに対して
      割り当てられるCPU時間とか、優先度とかをきっちり管理してますので。

      メインフレームからUNIX系マシンを使うようになって、よく感じたのは、
      このあたりです。南下ちょっとおかしな事すると、すぐにシステム全体に
      影響するという。

      親コメント
      • UNIX屋からM/Fの運用に最近なったのですが、夜間バッチの延伸とかたまにあるのですけど、
        無限ループと投入データが多かったための延伸のプロセスと区別して
        アベンドとか可能なのですか??

        UNIXも最近は物理CPUが増えたので無限ループプロセスが1個ぐらい出現しても
        全体のCPU不足にはなかなかならないですね。
        オンラインプロセスの無限ループor長時間化プロセスの発見が適当になっているとは
        思いますが。

        確かにオンラインのトラブルだとM/Fで長時間化系は聞かないかな...
        ユーザがくそ重いリクエストを出して、「応答無いな」と繰り替えしリクエストを
        出すようなトラブル(これも輻輳崩壊の一種かな)になるとか。
        親コメント
        • by Anonymous Coward

          Xorg にて radeon サーバが常に CPU 100% なんだけど、
          ちょっと調べてもどうにかする方法がわからず。

          でも 8 core な PC で使っているもんで、
          Xorg が 100% なくらい全然オッケーということで放置してます…

          計算機の高速化により問題が解決される例ということで(違

          • by Anonymous Coward

            それって無限ループじゃ無いと思うんだが

    • 2秒ぐらいですかね?

      # 上のコメントは分かっててマジレスしてるんですよ…ね?
      親コメント
      • 今度出たCrayのスーパーコンピュータはとても速い。無限ループを6秒で抜ける。
        今度出たCrayのスーパーコンピュータはとても速い。haltを2回書かないと止まらない。

typodupeerror

192.168.0.1は、私が使っている IPアドレスですので勝手に使わないでください --- ある通りすがり

読み込み中...