- Xác nhận hiện tượng game bị crash do tràn biến trong engine DOOM
- Tiến hành thí nghiệm chạy DOOM suốt 2,5 năm trong môi trường sử dụng thực tế
- Khi giá trị biến tiếp tục tăng, nó chạm ngưỡng tràn và trò chơi kết thúc đúng vào thời điểm được dự đoán
- Thí nghiệm được thực hiện trong môi trường chạy tự động dài hạn bằng PDA và bộ DIY UPS
- Bài kiểm tra này chứng minh rằng một vấn đề mang tính lý thuyết cũng có thể thực sự xảy ra ngoài đời
Bối cảnh và động lực thí nghiệm
- Khoảng 2 năm rưỡi trước, khi đọc một bài viết về cấu trúc và cách hoạt động của engine DOOM, tác giả phát hiện biến dùng để theo dõi việc chạy demo tiếp tục tăng sau mỗi lần bắt đầu demo
- Biến này được so sánh với giá trị trước đó, nhưng vì giá trị cứ lặp đi lặp lại mà tăng lên nên cuối cùng tiềm ẩn nguy cơ tràn số
- Trong môi trường sử dụng thông thường, rất khó để đạt tới tình huống tràn này, nhưng tác giả quyết định tự tiến hành thử nghiệm để xem thực tế mất bao lâu
Phương pháp và quá trình thí nghiệm
- Thông qua phép tính đơn giản, tác giả ước tính cần khoảng 2 năm rưỡi thời gian chạy để xảy ra tràn
- Để kiểm chứng thực tế, tác giả cài DOOM lên thiết bị PDA rồi cấp nguồn bằng bộ DIY UPS dùng pin 18650
- Thiết bị này được kết nối với cổng USB của router để duy trì liên tục nguồn điện 5V
- Sau khi thiết lập hệ thống để chạy liên tục trong môi trường tự động sạc, tác giả gần như để mặc nó trong phần lớn thời gian
Sự cố crash và kết quả
- Khoảng 2 năm rưỡi sau khi bắt đầu thí nghiệm, tác giả xác nhận có thông báo popup xuất hiện trên màn hình thiết bị
- DOOM đã chuyển sang trạng thái crash cứng do tràn số đúng như dự đoán
- Kết quả thí nghiệm chứng minh rằng hiện tượng game kết thúc do tràn biến thực sự có thể xảy ra trên phần cứng thật và trong môi trường phần mềm thật
Kết luận và hàm ý
- Thí nghiệm nhấn mạnh điểm cần lưu ý trong lập trình đối với các biến tích lũy tăng dần trong thời gian dài
- Nó xác nhận bằng thực nghiệm rằng lỗi tràn số vốn chỉ được xem là khả năng trên lý thuyết có thể thực sự bùng phát trong đời thực
- Đồng thời gióng lên hồi chuông cảnh báo về các lỗi ẩn trong mã legacy hoặc phần mềm chạy trong thời gian dài
1 bình luận
Ý kiến trên Hacker News
Khoảng 1 năm trước, trong lúc xem xét hệ thống bộ đếm thời gian của Crash Bandicoot, tôi phát hiện ở Crash 3 có một giá trị kiểu int32 cứ tiếp tục tăng lên, với cấu trúc chỉ reset khi chết; nếu để máy chạy trong 2,26 năm thì sẽ xảy ra tràn số, lúc đó thời gian trở thành “âm” và game hỏng theo nhiều cách khá buồn cười; tôi đã làm một video về chuyện này liên kết YouTube
Trong Final Fantasy 9, để lấy được một vũ khí nhất định thì phải đến khu vực cuối game trong vòng 12 giờ (bản châu Âu là 10 giờ), nhưng do lỗi nên ngay cả khi cứ để máy chạy suốt 2 năm cho đến khi bộ đếm thời gian tràn số thì vẫn có thể nhận được nó; cứ thong thả chờ cũng đạt mục tiêu, liên kết giải thích chi tiết
Thật lạ là trong video của bạn không hề đùa chữ với từ "crash" lấy một lần nào, trong khi hiện tượng treo máy cũng có thể gọi là crash; hơi tiếc một chút
Tôi tự hỏi việc dùng signed integer làm mặc định để theo dõi bộ đếm thời gian có phổ biến không; nếu là unsigned thì thời gian tới lúc tràn số sẽ dài gấp đôi, nên tôi thắc mắc vì sao họ lại chọn như vậy
Tôi nghĩ nhiều game hồi đó có cấu trúc như vậy; SotN cũng có một bộ đếm thời gian toàn cục; trên hệ thống 32-bit, với những game chỉ được dùng vài tháng đến cùng lắm vài năm, người ta hẳn không thấy cần phải kiểm thử chuyện thời gian trôi qua nhiều năm; hồi đó chắc chẳng ai tưởng tượng phần mềm mình viết ra lại bị hack, phân tích, đảo ngược kỹ thuật như vậy; bản thân chúng ta khi lập trình bình thường cũng không mấy khi cân nhắc quá nhiều đến điều đó
Đây mới là mở khóa Time Twister thực thụ
Đây đúng là tình huống đủ khiến người ta cảm thấy game không thể chơi được; mong là ai đó sẽ sửa nó; Doom thực sự là một game tuyệt vời và cứ vài năm tôi lại quay lại chơi; bản reboot năm 2016 cũng rất vui, nhưng các bản sau đó thì cá nhân tôi không thích lắm
Có một cộng đồng dành cho những người thích lối chơi kiểu Doom cổ điển r/boomershooters
Tôi cũng vậy; thiết kế metroidvania và cấu trúc hub ở nhà trong các bản gần đây không mang lại cảm giác xưa cũ đó; tôi thích kiểu tiến trình đơn giản hơn: chạy, hạ địch, tìm bí mật, rồi sang màn tiếp theo
Tôi cũng thế, đặc biệt là tôi rất thích chế độ brutality
Thú vị thật, giờ Doom thuộc sở hữu của Microsoft cùng với Quake, StarCraft, WarCraft, Overwatch, toàn bộ game phiêu lưu của Infocom và Sierra, và cả Halo nữa; từ năm 1996 Microsoft đã cố nắm phần lớn tài sản trí tuệ của game PC, nên có thể xem như họ gần đạt được mục tiêu đó rồi
Bản 2016 là game FPS chơi đơn hay nhất mà tôi từng chơi; thứ duy nhất sánh được với nó là Titan Fall 2
Tôi tự hỏi phần cứng có chức năng trap overflow hay không; tôi từng đọc bài viết về cách engine Doom hoạt động và thấy rằng biến theo dõi demo vẫn tiếp tục tăng ngay cả khi demo tiếp theo bắt đầu; biến này được so sánh với một biến thứ hai lưu giá trị trước đó; tôi tò mò vì sao game thực sự lại bị crash
Phải cảm ơn vì họ đã biết trước nguyên nhân của lỗi; nếu không thì sau 2,5 năm mới nhận ra “chết tiệt, mình quên bật debug log rồi”
DOOM còn crash trước cả Windows CE
Điều làm tôi ấn tượng nhất là ứng dụng trên PDA đã chạy liên tục suốt 2,5 năm; tôi rất nghi ngờ liệu trên phần cứng hiện đại, bị mất Internet trong từng ấy thời gian, chuyện đó có còn khả thi không
Đúng là một thành tích đáng nể
Có vẻ trang web đã sập vì quá nhiều truy cập, nên tôi để liên kết archive.org ở đây liên kết bản lưu trên archive.org, tiếc là định dạng trang không được lưu đầy đủ nhưng phần văn bản vẫn còn
Có lẽ năm 2038 sẽ là một năm rất thú vị
Nhiều người bỏ qua vấn đề NTP sẽ xảy ra vào năm 2036; đến lúc đó mới là bữa tiệc thực sự bắt đầu
So với thời Y2K thì năm 2038 giờ có cảm giác gần hơn nhiều
Còn 13 năm để nâng cấp lên int 64-bit hoặc chuyển time_t sang kiểu long long; rất nhiều thiết bị nhúng hoặc hệ thống đóng đã ngừng hỗ trợ sẽ cần được chú ý riêng; OpenFirmware trên chiếc SunServer 600MP tôi từng dùng trước đây cũng gặp đúng vấn đề đó; may là giờ chuyện ấy không còn là điều tôi phải lo nữa
Giải quyết vấn đề đó chính là kế hoạch nghỉ hưu của tôi
Tôi không nghĩ bất kỳ tester nào mà tôi biết sẽ làm loại kiểm thử ở mức này; ngay trong hệ thống tôi đang làm việc, chỉ riêng hôm qua thôi tôi đã phải chờ hơn 5 lần để xác nhận xử lý lỗi sau timeout 30 giây, và chuyện đó cực kỳ khó chịu
Ngày trước Windows NT 4 cũng từng có một lỗi tương tự; đó là một bộ đếm độ chính xác cao dùng để đo uptime của hệ thống; trước Service Pack 3 (hoặc 2), người ta dùng scheduler để reboot hệ thống vào ngày 1 hằng tháng; nếu không thì sau khoảng 42 ngày uptime nó sẽ bị crash; đến cả Microsoft khi đó cũng không nghĩ một hệ điều hành máy chủ lại có thể chạy liên tục lâu đến thế
Xin thêm một lần nữa dành lời khen cho đội ngũ id Software; nếu được phát triển theo kiểu phổ biến ngày nay thì chắc nó đã chết vì phân mảnh bộ nhớ hoặc rò rỉ bộ nhớ từ lâu trước khi chạm mốc 2 năm rồi