DOOM、実機で2.5年の連続稼働後にクラッシュ発生を確認
(lenowo.org)- DOOMエンジンの変数オーバーフローによってゲームクラッシュが発生することを確認
- 実使用環境で2.5年間DOOMを実行する実験を実施
- 変数の値が増え続け、オーバーフローに達した時点で予想どおりゲームが終了
- 実験はPDAとDIY UPSを用いた長期自動実行環境で実施
- このテストは理論上の問題が現実でも実際に発生することを実証
実験の背景と動機
- 約2年半前、DOOMエンジンの構造と動作方式に関する記事を読んだ際、デモ実行の追跡に使われる変数がデモ開始のたびに増え続けることを発見
- この変数は直前の値と比較されるが、繰り返し値が大きくなることで、最終的にオーバーフローの危険を内包していた
- 通常の使用環境ではこのオーバーフローに到達しにくいが、実際にどれほど時間がかかるのかを確かめるため、直接実験することを決定
実験方法と過程
- 単純計算により、オーバーフローが発生するまでに約2年半のランタイムが必要だと推定
- 実際に確認するため、PDA端末にDOOMをインストールし、18650バッテリーを使ったDIY UPSで電源を供給
- その端末をルーターのUSBポートに接続し、5V電源を継続的に供給
- システムを自動充電環境で継続稼働するよう設定し、大半の時間は放置
クラッシュ発生と結果
- 実験開始から約2年半が経過した後、端末の画面にポップアップ通知が表示されたことを確認
- DOOMは予想どおり、オーバーフローによるハードクラッシュ状態に移行
- 実験の結果、変数オーバーフローによるゲーム終了現象が、実機および実際のソフトウェア環境でも発生することを実証
結論と示唆
- プログラミングにおいて、長時間にわたって累積的に増加する変数への注意が重要であることを強調
- 理論上の可能性にすぎないと思われていたオーバーフロー問題が現実で実際に起こりうることを実験的に確認
- レガシーコードや長時間動作するソフトウェアに潜む隠れた欠陥への警戒を促す
1件のコメント
Hacker Newsの意見
約1年前にCrash Bandicootのタイマーシステムを調べていたところ、Crash 3では
int32型の値が増え続けることに気づいた。死んだときにしかリセットされない仕組みで、2.26年つけっぱなしにするとオーバーフローが発生する。このとき時間が「マイナス」になり、ゲームがいろいろとおかしな壊れ方をする。これについての動画を作った: YouTubeリンクFinal Fantasy 9では特定の武器を手に入れるには12時間以内(欧州版では10時間以内)に終盤エリアへ到達する必要があるが、バグのため、タイマーがオーバーフローするまで2年間つけっぱなしにしても取得できる。のんびり待っていても目的達成になる。詳しい説明リンク
あなたの動画で一度も「crash」という言葉遊びをしなかったのが意外だ。フリーズ現象もcrashと呼べたのに、少し惜しい
タイマー追跡にsigned integerをデフォルトで使うのは一般的なのだろうか。unsignedならオーバーフローまでの時間は2倍になるはずなのに、なぜそうしたのか不思議だ
多くのゲームがそういう構造だったのだと思う。SotNにもグローバルタイマーがある。32ビット環境で、数か月から長くても数年遊ばれるゲームのために、わざわざ数年経過をテストする必要性は感じなかったのだろう。当時は、自分たちの作ったソフトウェアがハックされ、解析され、リバースエンジニアリングされることまで想像していなかったはずだ。私たちも普段プログラムを書くとき、そこまで強く意識はしない
真のTime Twisterアンロックだ
プレイ不能と感じてもおかしくない状況だ。誰かがぜひ直してくれればと思う。Doomは本当に素晴らしいゲームで、数年おきにいつも戻って遊んでしまう。2016年のリブートも楽しかったが、その後のタイトルは個人的にはいまひとつだった
クラシックなDoomスタイルのゲームプレイが好きな人向けのコミュニティがある: r/boomershooters
私も同じだ。最近のタイトルにあるメトロイドヴァニア的な設計やホームハブ構造は、昔の感覚を与えてくれない。走って、敵を倒して、秘密を見つけて、次のレベルへ進むというシンプルな流れのほうがいい感じだ
私も同感で、特に brutality モードが大好きだ
面白い事実だ。今やDoomはQuake、StarCraft、WarCraft、Overwatch、InfocomとSierraの全アドベンチャーゲーム、そしてHaloと並んでMicrosoftの所有物になっている。Microsoftは1996年からPCゲームの知的財産の大半を手に入れようとしていたのだから、ほぼ目的を達成したと言える
2016年作は、私が遊んだ中で最高のシングルプレイFPSだった。比肩できるのはTitan Fall 2くらいしかなかった
ハードウェアにオーバーフローをトラップする機能があるのか気になる。Doomエンジンの動作についての記事を読んだことがあり、デモ追跡変数が次のデモが始まっても増え続けると知った。この変数は前回の値を保存する2つ目の変数と比較される。実際のゲームでなぜクラッシュが起きたのか気になる
new < oldになる状況を想定せずにコードが書かれている。そのため、スタック破損のようなバグも簡単に起こりうる。Cでは、たとえばreturn値のない関数が値を返すべき場所まで到達した場合でも、平然と未定義動作を実行するバグの原因を前もって分かっていたことに感謝すべきだ。2.5年たってから「くそ、デバッグログを有効にするのを忘れてた」と気づいた可能性もあった
DOOMはWindows CEより先にクラッシュした
2.5年間、PDA上でアプリケーションが動き続けたことのほうに一番驚く。インターネット未接続のまま、最新ハードウェアで同じことが可能なのかかなり疑わしい
本当にすごい記録だ
サイトはアクセス集中で落ちたようなので、archive.orgのリンクを貼っておく: archive.org保存版リンク。残念ながらサイトの書式は完全には保存されていないが、テキストは残っている
2038年は興味深い年になりそうだ
多くの人は2036年のNTP問題を見落としている。真のパーティーはそこから始まる
y2kのころより、2038年のほうがずっと近く感じる
64ビット
intへのアップグレード、あるいはtime_tをlong long型へ切り替えるまであと13年ある。多くの組み込み機器やサポート終了済みのクローズドシステムには別途注意が必要だろう。昔使っていたSunServer 600MPのOpenFirmwareにも同じ問題があった。幸い、今はもう心配しなくていい問題だその問題を解決するのが私の引退後の計画だ
このレベルのテストは、私の知るどのテスターもやらないと思う。私が働いているシステムでも、昨日だけで30秒タイムアウト後のエラー処理を確認するために5回以上待たされて、とてもいらいらした
かつてWindows NT 4にも似たバグがあった。システムのuptimeを計測する高精度カウンターに関するものだ。Service Pack 3(または2)以前は、毎月1日にスケジューラでシステムを再起動させていた。そうしないと約42日稼働後にクラッシュした。Microsoftですら、サーバーOSがそんなに長時間動き続けるとは考えていなかったのだ
id Softwareチームには改めて称賛を送りたい。今どき一般的なやり方で開発されていたら、メモリ断片化やメモリリークのせいで2年を超える前に落ちていただろう