Chrono Mock
DilTürkçe

Windows’ta 2038 yılı sorununu test etmek

19 Ocak 2038’de 03:14:07 UTC’de, 1970’ten beri saniyeleri sayan 32 bitlik işaretli bir sayaç sona erer. Windows saati bunun ötesinde çalışmaya devam eder - kendi 32 bitlik kopyasını tutan programlar, dosya biçimleri ve kütüphaneler ise etmez. Bunları tüm makinenin tarihini 2038’e ayarlamadan tek bir uygulamada nasıl bulacağınız burada.

Hata hâlâ nerede olabilir

Windows saati, 1601’den beri 100 nanosaniyelik adımları sayan 64 bitlik bir sayaçtır; yani 2038’i bilmez. C çalışma zamanı kütüphanesinin time_t türü Visual Studio 2005’ten beri varsayılan olarak 64 bittir. Geriye 32 bitlik bir zaman seçen ya da üst yarısını yolda kaybeden kod kalır:

  • _USE_32BIT_TIME_T ile derlenmiş 32 bitlik sürümler ya da doğrudan _time32 ve __time32_t çağıranlar. Microsoft’un kendi belgeleri böyle bir uygulamanın 18 Ocak 2038’den sonra bozulabileceği konusunda uyarır.
  • Bir int ya da long içinde saklanan 64 bitlik zaman. Windows’ta ikisi de 32 bittir; 64 bitlik bir programda bile.
  • 1970’ten beri geçen saniyeleri 32 bitte tutan kütüphaneler, dosya biçimleri, ağ protokolleri ve veritabanı sütunları.
  • Yıl ekleyen kod. Yirmi yıllık bir lisans, otuz yıllık bir kredi planı ya da 2040’a kadar geçerli bir sertifika, 2038 gelmeden çok önce sınırı aşar.

Sınırı tek bir uygulamada aşmak

Sınır UTC cinsinden tanımlıdır ve --at oturum diliminde okunur; bu yüzden anı kendiniz yazıyorsanız dilimi UTC’ye sabitleyin. Hazır senaryo zaten mutlak bir UTC anı taşır ve dilime ihtiyaç duymaz.

# Senaryo: oturum doğrudan sınırda, 03:14:07 UTC’de başlar
chrono run "C:\apps\test.exe" --preset year-2038 --report session.txt

# Sınırdan on yedi saniye önce başlayın ve uygulamanın onu canlı geçmesine izin verin
chrono run "C:\apps\test.exe" --at 2038-01-19T03:13:50 --zone +00:00 --report session.txt

# Daha erken başlayıp x60 hızla çalıştırın - sınır yaklaşık 14 saniyede gelir
chrono run "C:\apps\test.exe" --at 2038-01-19T03:00:00 --zone +00:00 --mode x60

# Ya da bugünün tarihinde çalışıp uygulama açıkken sınırın üzerinden atlayın
chrono run "C:\apps\test.exe" --jump-after 5:2038-01-19T03:14:05 --zone +00:00

Sınırdan bir saniye sonra 32 bitlik işaretli bir sayaç -2.147.483.648 olur; bu da 13 Aralık 1901, 20:45:52 UTC olarak okunur. 1901’den bir tarih, negatif bir sayı, birdenbire süresi dolan ya da sıralamada en başa geçen bir öğe, tarih kodundan fırlatılan bir istisna - taşma dışarıdan böyle görünür.

Gerçek saati 2038’e ayarlamak buraya varmanın diğer yoludur ve en çok şeyi bozan yoldur. Sistem tarihini değiştirince ne olur →

Programa ulaştığını doğrulamak

Programın 2038’i hiç görmediği için geçen bir test, hiç test olmamasından kötüdür. Her oturumun sonundaki rapor, programın hangi saati ve kaç kez okuduğunu söyler:

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)

session satırı, uygulamanın saatinin sınırı aştığını doğrular. Çağrı sayılarıyla birlikte works kararı, programın saati okuduğu ve 2038 tarihini aldığı anlamına gelir; works partially ise başka bir yoldan okuduğu kanalları adlandırır. Kararlar ne anlama gelir →

Geçen bir testin kanıtlamadığı şeyler

  • Yalnızca programın kendi saati kaydı. Bir dosyadan ya da veritabanından yüklediği tarih orada neyse odur; dolayısıyla verinin içindeki 2038 tarihi ayrı bir testtir. Tarih hesaplayıcı bu tarihleri sizin için hesaplar: chrono calc --base 2038-01-19T03:14:07 --zone +00:00 --shift +1s
  • Programın konuştuğu bir sunucu hâlâ gerçek tarihte çalışır. O taraftaki 32 bitlik bir sınır erişimin dışındadır ve oturum, programın bir ağ bağlantısı açtığını görünce uyarır.

Deneyin