Chrono Mock
BahasaBahasa Indonesia

Menguji masalah tahun 2038 di Windows

Pada 19 Januari 2038 pukul 03:14:07 UTC, penghitung detik sejak 1970 yang bertanda 32 bit habis. Jam Windows terus berjalan melewatinya - program, format berkas, dan pustaka yang menyimpan salinan 32 bit sendiri tidak. Berikut cara menemukannya di satu aplikasi, tanpa menyetel tanggal seluruh mesin ke 2038.

Di mana bug itu masih bisa bersembunyi

Jam Windows adalah penghitung 64 bit berisi langkah 100 nanodetik sejak 1601, jadi ia tidak mengenal 2038. Tipe time_t pada pustaka runtime C bernilai 64 bit secara bawaan sejak Visual Studio 2005. Yang tersisa adalah kode yang memilih waktu 32 bit atau kehilangan separuh atasnya di tengah jalan:

  • Build 32 bit yang dikompilasi dengan _USE_32BIT_TIME_T, atau yang memanggil _time32 dan __time32_t secara langsung. Dokumentasi Microsoft sendiri memperingatkan bahwa aplikasi seperti itu bisa gagal setelah 18 Januari 2038.
  • Waktu 64 bit yang disimpan dalam int atau long. Di Windows keduanya 32 bit, bahkan di program 64 bit.
  • Pustaka, format berkas, protokol jaringan, dan kolom basis data yang menyimpan detik sejak 1970 dalam 32 bit.
  • Kode yang menambahkan tahun. Lisensi dua puluh tahun, jadwal cicilan tiga puluh tahun, atau sertifikat yang berlaku hingga 2040 melewati batas itu jauh sebelum 2038 tiba.

Melewati batas di satu aplikasi

Batas itu didefinisikan dalam UTC dan --at dibaca dalam zona sesi, jadi kunci zona ke UTC saat Anda menulis momennya sendiri. Skenario siap pakai sudah membawa momen UTC absolut dan tidak memerlukan zona.

# Skenarionya: sesi dimulai tepat di batas, 03:14:07 UTC
chrono run "C:\apps\test.exe" --preset year-2038 --report session.txt

# Mulai tujuh belas detik sebelumnya dan biarkan aplikasi melewatinya secara langsung
chrono run "C:\apps\test.exe" --at 2038-01-19T03:13:50 --zone +00:00 --report session.txt

# Mulai lebih awal dan jalankan dengan kecepatan x60 - batasnya tiba dalam sekitar 14 detik
chrono run "C:\apps\test.exe" --at 2038-01-19T03:00:00 --zone +00:00 --mode x60

# Atau jalankan dengan tanggal hari ini dan lompati batasnya saat aplikasi terbuka
chrono run "C:\apps\test.exe" --jump-after 5:2038-01-19T03:14:05 --zone +00:00

Satu detik setelah batas, penghitung 32 bit bertanda menjadi -2.147.483.648, yang terbaca sebagai 13 Desember 1901, 20:45:52 UTC. Tanggal tahun 1901, angka negatif, butir yang tiba-tiba kedaluwarsa atau terurut paling depan, pengecualian yang dilempar dari kode tanggal - begitulah wujud luapan itu dari luar.

Menyetel jam asli ke 2038 adalah cara lain untuk sampai ke sini, dan cara yang paling banyak merusak. Apa yang terjadi saat Anda mengubah tanggal sistem →

Memastikan batas itu sampai ke program

Pengujian yang lolos karena program tidak pernah melihat 2038 lebih buruk daripada tanpa pengujian. Laporan di akhir setiap sesi menyebutkan jam mana yang dibaca program dan berapa kali:

Chrono Mock - session report
  target:   .\build\test.exe
  verdict:  WORKS - time substitution took effect  (processes: 1)
            every process that read time saw the session clock
  session:  fake clock reached 2038-01-19T03:14:08
            real elapsed 1.3s, fake elapsed 1.3s
  covered channels (substituted, with call counts, 10 calls in all):
            - pid 21240: GetSystemTimeAsFileTime (5 calls)
            - pid 21240: GetLocalTime (5 calls)

Baris session memastikan jam aplikasi telah melewati batas. Putusan works dengan hitungan panggilan berarti program membaca jam dan menerima tanggal 2038; works partially menyebutkan kanal yang dibacanya lewat jalur lain. Apa arti putusan-putusan itu →

Yang tidak dibuktikan oleh pengujian yang lolos

  • Hanya jam milik program itu sendiri yang bergeser. Tanggal yang ia muat dari berkas atau basis data adalah apa yang tersimpan di sana, jadi tanggal 2038 di dalam data adalah pengujian tersendiri. Kalkulator tanggal menghitung tanggal semacam itu untuk Anda: chrono calc --base 2038-01-19T03:14:07 --zone +00:00 --shift +1s
  • Server yang diajak bicara program tetap berjalan di tanggal asli. Batas 32 bit di sisi itu berada di luar jangkauan, dan sesi memperingatkan saat melihat program membuka koneksi jaringan.

Cobalah