
2038年問題(Y2038、[1] Y2K38、Y2K38スーパーバグ、またはエポカリプス[2][3]としても知られる)は、 2038年1月19日03:14:07 UTC以降の時刻を一部のコンピュータシステムが表現できなくなるという時間計算の問題である。
この問題は、Unix時間(Unixエポック (1970年1月1日00:00:00 UTC )からの経過秒数)を測定し、それを符号付き32ビット整数に格納するシステムで発生します。データ型の最大値を超えると、整数は最小値にオーバーフローし、システムはそれを過去の値として解釈します。この問題は2000年問題に似ていますが、10進数ではなく2進数(バイナリ)の時間表現の制限に起因します。
重要な計算に時間を使用するコンピュータシステムは、2038 年問題に対処しないと致命的なエラーに遭遇する可能性があります。将来の日付を使用する一部のアプリケーションは、すでにこのバグに遭遇しています。[ 4 ] [ 5 ]最も脆弱なシステムは、レガシーシステムや組み込みシステムなど、更新頻度が低い、またはまったく更新されないシステムです。最新のシステムとソフトウェアの更新では、符号付き64 ビット整数を使用することでこの問題に対処しています。符号付き64 ビット整数は、オーバーフローするまでに 2920 億年かかります。これは、宇宙の現在の推定年齢の約 21 倍です。[ 6 ]
多くのコンピュータシステムは、デジタル時刻計測の国際標準であるUnix時間を使用して時刻と日付を測定します。Unix時間は、 Unixエポックとして知られる1970年1月1日00:00:00 UTCからの経過秒数(閏秒は除く)として定義されます。
Unix の時刻は、歴史的に符号付き 32 ビット整数としてエンコードされてきました。符号付き 32 ビット整数は、整数値を表す 32 個のバイナリ数字(ビット)で構成されるデータ型で、「符号付き」とは、その数値が正の数と負の数、およびゼロを表すことができることを意味します。通常、 2 の補数形式で格納されます。[ a ]したがって、符号付き 32 ビット整数は、−(2 31 ) から 2 31 − 1 までの整数値のみを表すことができます。したがって、符号付き 32 ビット整数を使用して Unix 時刻を格納する場合、格納できる最新の時刻は、エポックから 2 31 − 1 ( 2,147,483,647 ) [ b ]秒後、つまり2038 年 1 月 19 日 03:14:07 UTC になります。[ 7 ]この値をエポック ( 03:14:08 )から 2 31秒後に 1 秒増やそうとするシステムは、整数オーバーフローが発生し、意図せず符号ビットが反転して負の数を示します。これにより、整数値は −(2 31 ) に変更され、エポックの後ではなくエポックの2 31秒前となり、システムはこれを 1901 年 12 月 13 日 20:45:52 UTCと解釈します。ここから、システムはゼロに向かってカウントアップを続け、その後再び正の整数をカウントアップします。多くのコンピュータシステムは重要な機能を実行するために時間計算を使用しているため、このバグは深刻な問題を引き起こす可能性があります。
符号付き32ビット時間表現を使用するデータ構造を用いるシステムには、固有の障害リスクが存在する。こうしたデータ構造の完全なリストを作成することは事実上不可能だが、Unix時間問題を抱えていることが知られているデータ構造がいくつか存在する。
UNIX_TIMESTAMP()。_gmtime32のマッピングとして機能する) フォーマットが2038年 1 月 19 日 00:00:00 にロールオーバーします。2005 年より前のバージョンの Visual Studio でビルドされたソフトウェアはに対応することが知られており、Visual Studio 2019 までの 32 ビットバージョンの Visual Studio でビルドする際に を指定することで、この対応を強制できます。[ 14 ]time_t_gmtime_gmtime32_USE_32BIT_TIME_T計算または診断ログに日付を使用する組み込みシステムは、Y2038 問題の影響を最も受けやすい。[ 1 ]コンピュータ システム技術の世代交代が 18〜24 か月で行われる現代においても、組み込みシステムは、それが組み込まれているマシンの寿命まで使用できるように設計されている。これらのシステムの一部は、2038 年にもまだ使用されている可能性がある。これらのシステムで実行されているソフトウェアをアップグレードすることは困難、あるいは場合によっては不可能であり、32 ビットの制限を修正するには最終的に交換が必要になる可能性がある。
航空機から自動車まで、多くの輸送システムでは組み込みシステムが広く利用されています。自動車システムでは、アンチロックブレーキシステム(ABS)、電子安定制御(ESC/ESP)、トラクションコントロール(TCS)、自動四輪駆動などが含まれます。航空機では、慣性誘導システムやGPS受信機が使用される場合があります。[ c ]
組み込みシステムのもう一つの主要な用途は、携帯電話やインターネット接続機器(ルーター、無線アクセスポイント、IPカメラなど)を含む通信機器であり、これらの機器は正確な日時を保存する必要があり、ますますUnix系オペレーティングシステムに基づいている。
しかし、これはすべての組み込みシステムがY2038問題に悩まされることを意味するものではありません。なぜなら、そのようなシステムの多くは日付へのアクセスを必要としないからです。日付へのアクセスを必要とするシステムのうち、絶対的な時刻や日付ではなく、時刻や日付の差のみを追跡するシステムは、計算の性質上、大きな問題は発生しません。これは、CARB(カリフォルニア州大気資源局)などの法規制基準に基づく自動車診断の問題です。[ 15 ]
2006 年 5 月、 AOLserverソフトウェアで Y2038 問題の初期兆候が見られたという報告が浮上しました。このソフトウェアは、タイムアウトしないはずのデータベース要求を処理するために、応急処置的な方法で設計されていました。この特殊なケースを具体的に処理するのではなく、初期設計では単に将来の任意の日付をタイムアウトとして指定し、デフォルト設定では要求が最大 10 億秒後にタイムアウトするようにしていました。しかし、2038 年のカットオフ日の 10 億秒前は 2006 年 5 月 13 日 01:27:28 UTC であるため 、この時刻以降に送信された要求は、カットオフ日を超えるタイムアウト日になります。これにより、タイムアウトの計算がオーバーフローし、実際には過去の日付が返され、ソフトウェアがクラッシュしました。問題が発見されたとき、AOLServer のオペレーターは設定ファイルを編集してタイムアウト値をより低い値に設定する必要がありました。[ 4 ] [ 5 ]
32ビットシステムで生成された多くの種類の自己署名CA証明書は、ロールオーバーポイントを超える非常に長い有効期限を持つ可能性があり、正しく機能しなくなり、サービス(たとえばVPN )やそれらを使用するサイトでのHTTPS検証に影響を及ぼします。[ 16 ]
Microsoft Exchange Serverインストールの MS Filtering Engine Update マルウェア対策機能が、2022 年 1 月 1 日の更新後に壊れてしまいました。この機能は、処理された UpdateVersion 番号 (9 桁または 10 桁の YY-MM-DD-n 形式を使用) を Unix タイム スタンプ番号にマッピングしていましたが、これらの時刻は大きく異なっていたため、エンジンが 220101001 (22-01-01 v001) の更新を受信したとき、これは末尾近くに余分なゼロが付いた 2201010001 を意味すると解釈し、32 ビットの Unix 時刻の番号にマッピングしようとしましたが、2147483647 より大きいため失敗しました。[ 17 ]影響を受けた Exchange サーバーは、マルウェア対策機能を無効にしない限り動作せず、2022 年 1 月 5 日に自動修正プログラムが公開されました。
Oracle Access Management バージョン 10.1.4.3 for Windowsでは、Identity Console コンポーネントが、UI設定を含む Cookie を500,000,000 秒後 (約 15 年 312 日) に有効期限を設定します。2022年 3 月 17 日 02:20:48 UTC頃から 、この有効期限は 2038 年 1 月 19 日を超えているため、呼び出しで指定された数値を Cookie に書き込む日付に変換できないため、特定の検索アクティビティで例外 が発生します。 [ 18 ]gmtime_r()
2038 年問題に対する普遍的な解決策はありません。たとえば、C 言語time_tでは、データ型の定義を変更すると、日付と時刻の表現が符号付き 32 ビット整数の性質に依存しているアプリケーションでコードの互換性のtime_t問題が発生します。time_t符号なし 32 ビット整数に変更すると、範囲が 2106 年[ 19 ] (具体的には、2106 年 2 月 7 日日曜日の 06:28:15 UTC) まで拡張されますが、1970 年より前の日付を保存、取得、または操作するプログラムに悪影響を及ぼします。これは、そのような日付が負の数で表現されるためです。既存のシステムで型のサイズをtime_t64 ビットに増やすと、構造体のレイアウトと関数のバイナリ インターフェースに互換性のない変更が発生します。
64 ビットハードウェアで動作するように設計されたほとんどのオペレーティングシステムは、すでに符号付き 64 ビットtime_t整数を使用しています。符号付き 64 ビット値を使用すると、宇宙の推定年齢 の 20 倍以上大きい新しいラップアラウンド日付が導入されます。これは、約 2920億年後です。 [ 20 ]ただし、64 ビット オペレーティングシステム上のソフトウェアは、タイムスタンプの処理に 32 ビット整数を使用することで、依然として問題を引き起こす可能性があります。[ 21 ]日付の計算を行う能力は、年として 1900 から始まる符号付き 32 ビット整数値を使用するという事実によって制限されますtm_year。これにより、年は最大 2,147,485,547 (2,147,483,647 + 1900) に制限されます。[ 22 ]
代替案として、符号付き 64 ビット整数にエポック (通常は 1970 年 1 月 1 日または 2000 年 1 月 1 日) からのミリ秒またはマイクロ秒を格納する方法 (既に使用されているものもある) があり、マイクロ秒の分解能で 292,000 年以上の最小範囲が提供されます。 [ 23 ] [ 24 ]特に、Java と JavaScript が絶対タイムスタンプを「1970 年 1 月 1 日からのミリ秒」として表現するために 64 ビット符号付き整数を使用する方法は、今後292 百万年間は正しく機能します。新しい時間表現に関する他の提案では、異なる精度、範囲、サイズ (ほぼ常に 32 ビットより広い) が提供されるほか、閏秒の処理など、関連する他の問題も解決されます。特に、TAI64 [ 25 ]は、秒と基準フレームを定義するための現在の国際リアルタイム標準である国際原子時(TAI) 標準の実装です。
time_ttime_t32 ビットおよび 64 ビットアーキテクチャの両方で 64 ビットを使用しています。32 ビットの古い NetBSD リリース用にコンパイルされたアプリケーションはtime_tバイナリ互換レイヤーを介してサポートされますが、そのような古いアプリケーションは依然として Y2038 の問題に悩まされます。[ 28 ]time_t、 32ビットおよび64ビットアーキテクチャの両方で64ビットを使用しています。NetBSDとは対照的に、バイナリ互換性レイヤーはありません。そのため、32ビットを想定しているアプリケーションtime_tや、時間値を保存するために異なるものを使用しているアプリケーションはtime_t動作しなくなる可能性があります。[ 29 ]time_t当初、64 ビットアーキテクチャのみに64 ビットを使用していました。後方互換性のため、純粋な 32 ビットABI は変更されませんでした。 [ 30 ] 2020 年のバージョン5.6以降、32 ビットアーキテクチャでも 64 ビットがサポートされるようになりました。これは主に組み込み Linuxtime_tシステムのために行われました。[ 31 ]time_tプリプロセッサマクロを定義することで有効にできます。[ 32 ]_TIME_BITS64time_t、32 ビット i386 を除くすべての 32 ビットおよび 64 ビット アーキテクチャで64 ビットを使用し、32 ビット i386 ではtime_t代わりに符号付き 32 ビットを使用します。[ 33 ]time_t。新しい環境であったため、特別な互換性対策は必要ありませんでした。[ 30 ]struct nfstime4 {int64_t seconds; uint32_t nseconds;}バージョン4では、2000年12月以降、時間フィールドが次のように定義されています。[ 34 ]バージョン3では、符号なし32ビット値が次のようにサポートされていますstruct nfstime3 {uint32 seconds; uint32 nseconds;};。[ 35 ]秒フィールドの値が0より大きい場合は、1970年1月1日(0時)以降の日付を示します。秒フィールドの値が0より小さい場合は、1970年1月1日(0時)以前の日付を示します。どちらの場合も、最終的な時間表現のために、nseconds(ナノ秒)フィールドが秒フィールドに追加されます。time_t。[ 39 ] 1998 年に実施された Y2K 対応作業の一環として、CRTL は時刻を表すために符号なし 32 ビット整数を使用するように変更され、範囲がtime_t2106 年 2 月 7 日まで拡張されました。 [ 40 ]FROM_UNIXTIME()、、UNIX_TIMESTAMP()およびは、CONVERT_TZ()それらをサポートするプラットフォームで 64 ビット値を処理します。これには、Linux、macOS、および Windows の 64 ビット版が含まれます。[ 41 ] [ 42 ]以前のバージョンでは、などの組み込み関数は、2038 年 1 月 19 日03:14:07 UTCUNIX_TIMESTAMP()以降に 0 を返します。[ 43 ]TIMESTAMPと関数FROM_UNIXTIME()、、UNIX_TIMESTAMP()およびが、CONVERT_TZ()Linux、macOS、および Windows の 64 ビット版で符号なし 32 ビット値を処理します。[ 44 ]これにより範囲が 2106-02-07 06:28:15 まで拡張され、ユーザーはストレージ レイアウトを変更することなく、このようなタイムスタンプ値をテーブルに保存できるようになり、既存のユーザー データとの完全な互換性が維持されます。time_t限り、CRT は 64 ビットを使用します。 [ 45 ]ただし、Windows API自体は 2038 年バグの影響を受けません。Windowsは内部的に、1601 年 1 月 1 日からの 100 ナノ秒間隔の数を 64 ビット符号付き整数で追跡しており、これは30,828年までオーバーフローしません。[ 46 ]_USE_32BIT_TIME_T_USE_32BIT_TIME_T、64 ビット版の Visual Studio でビルドする場合にも許可されていません。[ 14 ]{{cite web}}: CS1 maint: url-status (リンク)