Chrono Mock
JazykČeština

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_T nebo přímo volající _time32 a __time32_t. Dokumentace Microsoftu varuje, že taková aplikace může po 18. lednu 2038 selhat.
  • 64bitový čas uložený do int nebo long. 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í.

Vyzkoušejte