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_Tile derlenmiş 32 bitlik sürümler ya da doğrudan_time32ve__time32_tçağıranlar. Microsoft’un kendi belgeleri böyle bir uygulamanın 18 Ocak 2038’den sonra bozulabileceği konusunda uyarır.- Bir
intya dalongiç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.