2038年問題を再発させるコードが多数の場所にコピーされてしまっている
2038年問題はUNIX時間のオーバーフローに伴ってプログラムが誤動作するというものですが、既にほとんどのプログラムで解決済みとされています。しかし、ゲーム開発エンジニアのエイドリアンさんがMicrosoftのドキュメント上に2038年問題を引き起こすコードが掲載されているのを発見。そのコードをコピーしたプログラムでは2038年問題が発生してしまうと警告を行っています。
Year 2038 problem is still alive and well | Silent’s Blog
https://cookieplmonster.github.io/2022/02/17/year-2038-problem/
UNIX系のOSでは時刻情報を扱う際に1970年1月1日0時0分からの経過秒数として表される「UNIX時間」を利用しています。かつて、UNIX時間はシステム内部において符号付き32ビット整数の形式で格納されており、21億4748万3647秒までしか扱えないという問題がありました。このため、1970年1月1日0時0分から21億4748万3647秒経過したタイミングでシステムが誤作動を起こすことが懸念され、このタイミングが2038年に到来することから「2038年問題」と呼ばれ注意喚起されてきました。
2038年問題を解決するために、多くのOSにおいてUNIX時間の実装が符号付き64ビット整数に変更されてきました。符号付き64ビット整数ではオーバーフローが発生するまで2920億年かかるため、人類にとって必要な期間を全て扱うことが可能になっています。こうして、2038年問題についてエンジニアが頭を悩ませる必要は無くなったように見えました。
しかしある日、エイドリアンさんはMicrosoftのドキュメントの「Converting a time_t value to a FILETIME」という記事でUNIX時間をWindowsのFILETIMEに変換するコードとして下記のコードが掲載されているのを発見したとのこと。
#include <windows.h> #include <time.h> void TimetToFileTime(time_t t, LPFILETIME pft) { LONGLONG time_value = Int32x32To64(t, 10000000) + 116444736000000000; pft->dwLowDateTime = (DWORD) time_value; pft->dwHighDateTime = time_value >> 32; }
エイドリアンさんはこのコードを見て「Int32x32To64」という文字列に不安を覚え、詳しく調べてみたそうです。すると、「Int32x32To64」は下記のコードで定義されるマクロでした。
#define Int32x32To64(a, b) ((__int64)(((__int64)((long)(a))) * ((long)(b))))
「Int32x32To64」は2つの入力を持ちますが、その入力を最初に32ビットに変換し、その後2つの入力を乗算して64ビットで返しています。従って、このマクロにUNIX時間を入力すると32ビットに変換する時にオーバーフローしたデータが失われ、2038年問題を再び引き起こしてしまいます。エイドリアンさんは2021年11月にMicrosoftに対して修正の提案を行い、すぐにドキュメントがアップデートされました。
これで解決かと思いきや、エイドリアンさんはOpenRCT2の開発に取り組んでいる最中に、上記の「Int32x32To64」のコードが利用されているのを発見。多くのエンジニアがMicrosoftのドキュメントからコードをコピーしているため、かつて掲載されていた問題のあるコードが多数の場所で使われてしまっているとのこと。
エイドリアンさんが調べた限りでは、下記のリポジトリにて問題のあるコードが使用されていたとのことです。
O3DE
Dokany
Ceph-Dokan
libarchive
ghc::filesystem
ImageMagick
Cxbx-Reloaded
ReactOS
また、下記のリポジトリについては記事作成時点で既にエイドリアンさんの指摘を受けてコード修正済みとなっていました。
OpenRCT2
DuckStation
・関連記事
20年前の「2000年問題」の影響が時間を超えて各所で起こっているとの報告 - GIGAZINE
2000年問題が心配された1999年の年越し、Microsoft社内では何が起きていたのか? - GIGAZINE
なぜ複雑なシステムでは障害が発生しやすいのか - GIGAZINE
「World Wide Web」が生まれて10000日が経過 - GIGAZINE
なぜWindowsの標準ドライバーはすべて「2006年6月21日」のまま更新されないのか? - GIGAZINE
・関連コンテンツ
in ソフトウェア, Posted by log1d_ts
You can read the machine translated English article The code that reoccurs the Year 2038 pro….