Testování problému roku 2038 ve Windows
Dne 19. ledna 2038 ve 03:14:07 UTC dojde 32bitovému znaménkovému počítadlu sekund od roku 1970. Hodiny Windows běží dál - programy, formáty souborů a knihovny, které si ponechaly vlastní 32bitovou kopii, ne. Takto je najdete v jediné aplikaci, aniž byste nastavovali rok 2038 na celém počítači.
Kde se chyba může ještě skrývat
Hodiny Windows jsou 64bitové počítadlo kroků po 100 nanosekundách od roku 1601, takže rok 2038
neznají. Typ time_t v běhové knihovně jazyka C je od Visual Studia 2005 ve výchozím
nastavení 64bitový. Zůstává kód, který zvolil 32bitový čas nebo cestou ztratil horní polovinu:
- 32bitové sestavení přeložené s
_USE_32BIT_TIME_Tnebo přímo volající_time32a__time32_t. Dokumentace Microsoftu varuje, že taková aplikace může po 18. lednu 2038 selhat. - 64bitový čas uložený do
intnebolong. Ve Windows mají oba 32 bitů, i v 64bitovém programu. - Knihovny, formáty souborů, síťové protokoly a sloupce databází, které drží sekundy od roku 1970 v 32 bitech.
- Kód, který přičítá roky. Dvacetiletá licence, třicetiletý splátkový kalendář nebo certifikát platný do roku 2040 překročí hranici dlouho předtím, než rok 2038 nastane.
Překročení hranice v jediné aplikaci
Hranice je definována v UTC a --at se čte v pásmu sezení, takže při ručním zápisu
okamžiku nastavte pásmo na UTC. Hotový scénář už nese absolutní okamžik v UTC a pásmo nepotřebuje.
# Scénář: sezení začíná přímo na hranici, 03:14:07 UTC chrono run "C:\apps\test.exe" --preset year-2038 --report session.txt # Začít sedmnáct sekund před ní a nechat aplikaci hranici překročit za běhu chrono run "C:\apps\test.exe" --at 2038-01-19T03:13:50 --zone +00:00 --report session.txt # Začít dříve a běžet rychlostí x60 - hranice nastane asi za 14 sekund chrono run "C:\apps\test.exe" --at 2038-01-19T03:00:00 --zone +00:00 --mode x60 # Nebo běžet s dnešním datem a přeskočit ji, zatímco je aplikace otevřená chrono run "C:\apps\test.exe" --jump-after 5:2038-01-19T03:14:05 --zone +00:00
Sekundu za hranicí se 32bitové znaménkové počítadlo změní na -2 147 483 648, což se čte jako 13. prosince 1901, 20:45:52 UTC. Datum v roce 1901, záporné číslo, položka, která najednou propadla nebo se zařadila na začátek, výjimka vyhozená z kódu pro práci s daty - tak vypadá přetečení zvenčí.
Nastavení skutečných hodin na rok 2038 je druhá cesta, jak se sem dostat, a ta, která rozbije nejvíc. Co se stane, když změníte systémové datum →
Ověření, že to program zasáhlo
Test, který projde jen proto, že program rok 2038 nikdy neviděl, je horší než žádný test. Zpráva na konci každého sezení říká, jaké hodiny program četl a kolikrát:
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)
Řádek session potvrzuje, že hodiny aplikace přešly hranici. Verdikt works s počty volání znamená, že program hodiny četl a dostal datum z roku 2038; works partially jmenuje kanály, které četl jinou cestou. Co verdikty znamenají →
Co úspěšný test nedokazuje
- Posunuly se jen vlastní hodiny programu. Datum, které načte ze souboru nebo
databáze, je takové, jaké je tam uloženo, takže datum z roku 2038 v datech je samostatný test.
Kalkulačka dat taková data vypočítá za vás:
chrono calc --base 2038-01-19T03:14:07 --zone +00:00 --shift +1s - Server, se kterým program komunikuje, stále běží na skutečném datu. 32bitový limit na té straně je mimo dosah a sezení varuje, když uvidí, že program otevírá síťové spojení.