ทดสอบปัญหาปี 2038 บน Windows
เมื่อ 03:14:07 UTC ของวันที่ 19 มกราคม 2038 ตัวนับวินาทีนับจากปี 1970 แบบ 32 บิตมีเครื่องหมายจะหมดลง นาฬิกาของ Windows เดินต่อไปได้ - แต่โปรแกรม รูปแบบไฟล์ และไลบรารีที่เก็บสำเนา 32 บิตของตัวเองไว้ทำไม่ได้ นี่คือวิธีหาของเหล่านั้นในแอปเดียว โดยไม่ต้องตั้งวันที่ของทั้งเครื่องเป็นปี 2038
บั๊กยังซ่อนอยู่ที่ไหนได้บ้าง
นาฬิกาของ Windows เป็นตัวนับ 64 บิตของช่วงละ 100 นาโนวินาทีนับจากปี 1601 จึงไม่มีปี 2038 ชนิด time_t ของไลบรารีรันไทม์ C เป็น 64 บิตโดยค่าเริ่มต้นตั้งแต่ Visual Studio 2005 สิ่งที่เหลืออยู่คือโค้ดที่เลือกเวลา 32 บิต หรือทำครึ่งบนหล่นหายระหว่างทาง:
- บิลด์ 32 บิตที่คอมไพล์ด้วย
_USE_32BIT_TIME_Tหรือเรียก_time32และ__time32_tโดยตรง เอกสารของ Microsoft เองก็เตือนว่าแอปแบบนี้อาจล้มเหลวหลังวันที่ 18 มกราคม 2038 - เวลา 64 บิตที่เก็บไว้ใน
intหรือlongบน Windows ทั้งสองมีขนาด 32 บิต แม้ในโปรแกรม 64 บิตก็ตาม - ไลบรารี รูปแบบไฟล์ โปรโตคอลเครือข่าย และคอลัมน์ในฐานข้อมูลที่เก็บวินาทีนับจากปี 1970 ไว้ใน 32 บิต
- โค้ดที่บวกปีเข้าไป ไลเซนส์ยี่สิบปี ตารางผ่อนชำระสามสิบปี หรือใบรับรองที่ใช้ได้ถึงปี 2040 ข้ามเส้นนี้ไปนานก่อนที่ปี 2038 จะมาถึง
ข้ามเส้นแบ่งในแอปเดียว
ขีดจำกัดนี้นิยามเป็น UTC และ --at อ่านในโซนของเซสชัน ดังนั้นเมื่อเขียนช่วงเวลาเอง ให้ตรึงโซนเป็น UTC สถานการณ์สำเร็จรูปมีช่วงเวลา UTC แบบสัมบูรณ์อยู่แล้ว จึงไม่ต้องใช้โซน
# สถานการณ์: เซสชันเริ่มที่ขีดจำกัดพอดี 03:14:07 UTC chrono run "C:\apps\test.exe" --preset year-2038 --report session.txt # เริ่มก่อนหน้านั้นสิบเจ็ดวินาที แล้วให้แอปข้ามเส้นแบบสด ๆ chrono run "C:\apps\test.exe" --at 2038-01-19T03:13:50 --zone +00:00 --report session.txt # เริ่มเร็วกว่านั้นแล้วรันเร็วขึ้น 60 เท่า - ขีดจำกัดมาถึงในราว 14 วินาที chrono run "C:\apps\test.exe" --at 2038-01-19T03:00:00 --zone +00:00 --mode x60 # หรือรันด้วยวันที่ของวันนี้ แล้วกระโดดข้ามระหว่างที่แอปเปิดอยู่ chrono run "C:\apps\test.exe" --jump-after 5:2038-01-19T03:14:05 --zone +00:00
หนึ่งวินาทีหลังขีดจำกัด ตัวนับ 32 บิตมีเครื่องหมายจะกลายเป็น -2,147,483,648 ซึ่งอ่านได้เป็น 13 ธันวาคม 1901 เวลา 20:45:52 UTC วันที่ในปี 1901 ตัวเลขติดลบ รายการที่หมดอายุขึ้นมาเฉย ๆ หรือไปอยู่หัวลำดับ ข้อยกเว้นที่โยนออกมาจากโค้ดวันที่ - การล้นมองจากภายนอกหน้าตาเป็นแบบนี้
การตั้งนาฬิกาจริงเป็นปี 2038 คืออีกทางที่พามาถึงตรงนี้ และเป็นทางที่พังมากที่สุด จะเกิดอะไรขึ้นเมื่อคุณเปลี่ยนวันที่ของระบบ →
ตรวจว่าไปถึงโปรแกรมแล้ว
การทดสอบที่ผ่านเพราะโปรแกรมไม่เคยเห็นปี 2038 แย่กว่าไม่มีการทดสอบ รายงานตอนท้ายของทุกเซสชันบอกว่าโปรแกรมอ่านนาฬิกาเรือนไหนและกี่ครั้ง:
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 ยืนยันว่านาฬิกาของแอปผ่านขีดจำกัดไปแล้ว ผลสรุป works พร้อมจำนวนการเรียกหมายความว่าโปรแกรมอ่านนาฬิกาและได้รับวันที่ปี 2038 ส่วน works partially จะระบุช่องทางที่มันอ่านผ่านเส้นทางอื่น ผลสรุปมีความหมายว่าอะไร →
สิ่งที่การทดสอบที่ผ่านไม่ได้พิสูจน์
- เลื่อนไปเฉพาะนาฬิกาของโปรแกรมเอง วันที่ที่มันโหลดจากไฟล์หรือฐานข้อมูลก็คือสิ่งที่เก็บไว้ตรงนั้น ดังนั้นวันที่ปี 2038 ที่อยู่ในข้อมูลเป็นอีกการทดสอบหนึ่ง เครื่องคิดเลขวันที่คำนวณวันที่แบบนี้ให้คุณได้:
chrono calc --base 2038-01-19T03:14:07 --zone +00:00 --shift +1s - เซิร์ฟเวอร์ที่โปรแกรมคุยด้วยยังทำงานบนวันที่จริง ขีดจำกัด 32 บิตฝั่งนั้นอยู่นอกเหนือการเอื้อมถึง และเซสชันจะเตือนเมื่อเห็นโปรแกรมเปิดการเชื่อมต่อเครือข่าย