- ยืนยันการเกิดอาการ เกมแครช จาก variable overflow ใน DOOM engine
- ทำการทดลองให้ DOOM รันต่อเนื่อง 2.5 ปี ในสภาพแวดล้อมการใช้งานจริง
- เมื่อค่าตัวแปรเพิ่มขึ้นเรื่อย ๆ จนถึงจุด overflow เกมก็ ปิดตัวลงในจังหวะที่คาดไว้
- การทดลองดำเนินในสภาพแวดล้อมรันอัตโนมัติระยะยาวโดยใช้ PDA และ DIY UPS
- การทดสอบนี้พิสูจน์ว่า ปัญหาเชิงทฤษฎี สามารถเกิดขึ้นจริงได้ในโลกความเป็นจริง
ที่มาและแรงจูงใจของการทดลอง
- เมื่อราว 2 ปีครึ่งก่อน ผู้เขียนได้อ่านบทความเกี่ยวกับโครงสร้างและการทำงานของ DOOM engine แล้วพบว่า ตัวแปรที่ใช้ติดตามการรันเดโม จะเพิ่มขึ้นต่อเนื่องทุกครั้งที่เริ่มเดโม
- แม้ว่าตัวแปรนี้จะถูกนำไปเปรียบเทียบกับค่าก่อนหน้า แต่เมื่อค่ามันเพิ่มขึ้นซ้ำ ๆ ก็ย่อมมี ความเสี่ยงที่จะ overflow แฝงอยู่ในตัว
- ในสภาพแวดล้อมการใช้งานทั่วไป การจะไปถึงจุด overflow นี้ทำได้ยาก แต่จึงตัดสินใจทดลองด้วยตนเองว่าในความเป็นจริงต้องใช้เวลานานแค่ไหน
วิธีและขั้นตอนการทดลอง
- จากการคำนวณอย่างง่าย คาดว่าต้องใช้ เวลารันประมาณ 2 ปีครึ่ง จึงจะเกิด overflow
- เพื่อยืนยันจริง จึงติดตั้ง DOOM ลงบนอุปกรณ์ PDA แล้วจ่ายไฟด้วย DIY UPS ที่ใช้แบตเตอรี่ 18650
- เชื่อมต่ออุปกรณ์ดังกล่าวเข้ากับ พอร์ต USB ของเราเตอร์ เพื่อให้ได้รับไฟ 5V อย่างต่อเนื่อง
- จากนั้นตั้งค่าให้ระบบทำงานต่อเนื่องในสภาพแวดล้อมชาร์จอัตโนมัติ แล้วปล่อยให้รันเองเกือบตลอดเวลา
การเกิดแครชและผลลัพธ์
- หลังเริ่มการทดลองไปประมาณ 2 ปีครึ่ง พบว่าเกิด ป๊อปอัปแจ้งเตือน บนหน้าจอของอุปกรณ์
- DOOM เปลี่ยนเข้าสู่สถานะ แครชแบบรุนแรงจาก overflow ตามที่คาดไว้
- ผลการทดลองพิสูจน์ว่าอาการเกมปิดตัวจาก variable overflow สามารถเกิดขึ้นได้จริงบนฮาร์ดแวร์จริงและในสภาพแวดล้อมซอฟต์แวร์จริง
บทสรุปและนัยสำคัญ
- ตอกย้ำถึงข้อควรระวังในการเขียนโปรแกรมเกี่ยวกับ ตัวแปรที่สะสมค่าเพิ่มขึ้นเป็นเวลานาน
- ยืนยันเชิงทดลองว่า ปัญหา overflow ที่เคยถูกมองว่าเป็นเพียงความเป็นไปได้ทางทฤษฎี สามารถระเบิดขึ้นได้จริงในโลกความเป็นจริง
- ช่วยกระตุ้นให้ตระหนักถึง ข้อบกพร่องที่ซ่อนอยู่ ใน legacy code หรือซอฟต์แวร์ที่ทำงานยาวนานต่อเนื่อง
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เมื่อประมาณ 1 ปีก่อน ระหว่างดูระบบตัวจับเวลาของ Crash Bandicoot พบว่าใน Crash 3 มีค่าชนิด int32 ที่เพิ่มขึ้นเรื่อย ๆ และจะรีเซ็ตเฉพาะตอนตายเท่านั้น ถ้าเปิดทิ้งไว้ 2.26 ปีจะเกิด overflow จากนั้นเวลาก็จะกลายเป็นค่าติดลบ และเกมจะพังในแบบตลก ๆ หลายอย่าง จึงได้ทำวิดีโอเกี่ยวกับเรื่องนี้ไว้ ลิงก์ YouTube
ใน Final Fantasy 9 ถ้าจะเอาอาวุธชิ้นหนึ่งต้องไปถึงพื้นที่ช่วงท้ายเกมภายใน 12 ชั่วโมง (เวอร์ชันยุโรป 10 ชั่วโมง) แต่เพราะบั๊ก ถ้าเปิดเครื่องทิ้งไว้ต่อเนื่อง 2 ปีจนตัวจับเวลา overflow ก็ยังสามารถได้มันอยู่ดี แค่นั่งรอชิล ๆ ก็ทำเป้าหมายสำเร็จแล้ว ลิงก์อธิบายละเอียด
แปลกดีที่ในวิดีโอของคุณไม่ได้เล่นคำกับคำว่า "crash" เลยสักครั้ง ทั้งที่อาการค้างก็เรียกว่า crash ได้เหมือนกัน เลยแอบเสียดายนิดหน่อย
สงสัยว่าการใช้ signed integer เป็นค่าเริ่มต้นสำหรับติดตามตัวจับเวลานั้นพบได้บ่อยแค่ไหน ถ้าเป็น unsigned เวลาก่อน overflow ก็น่าจะเพิ่มขึ้นเป็นสองเท่า เลยสงสัยว่าทำไมถึงเลือกแบบนั้น
คิดว่าเกมจำนวนมากในยุคนั้นก็เป็นแบบนี้ SotN ก็มี global timer เหมือนกัน บนระบบ 32 บิต สำหรับเกมที่ใช้งานไม่กี่เดือนถึงอย่างมากไม่กี่ปี ก็คงไม่รู้สึกว่าจำเป็นต้องทดสอบการผ่านไปหลายปีขนาดนั้น ตอนนั้นคงไม่มีใครจินตนาการว่าซอฟต์แวร์ที่ตัวเองทำจะถูกแฮ็ก วิเคราะห์ หรือทำ reverse engineer กันขนาดนี้ พวกเราทุกวันนี้เวลาเขียนโปรแกรมก็ไม่ได้คิดถึงเรื่องแบบนั้นมากนัก
นี่แหละการปลดล็อก Time Twister ที่แท้จริง
ฟังดูเป็นสถานการณ์ที่ทำให้รู้สึกว่าเกมเล่นต่อไม่ได้เลย หวังว่าจะมีใครสักคนช่วยแก้ให้ Doom เป็นเกมที่ยอดเยี่ยมจริง ๆ และฉันก็มักจะกลับไปเล่นอีกทุก ๆ หลายปี รีบูตปี 2016 ก็สนุก แต่ภาคหลังจากนั้นส่วนตัวไม่ค่อยชอบ
มีคอมมูนิตี้สำหรับคนที่ชอบเกมเพลย์สไตล์ Doom คลาสสิกอยู่ r/boomershooters
ฉันก็เหมือนกัน ดีไซน์แบบ metroidvania และโครงสร้าง home hub ในภาคหลัง ๆ ไม่ได้ให้อารมณ์แบบเดิม ฉันชอบความเรียบง่ายแบบวิ่ง กำจัดศัตรู หา secret แล้วไปด่านถัดไปมากกว่า
ฉันก็เหมือนกัน โดยเฉพาะชอบ brutality mode มาก
เป็นข้อเท็จจริงที่น่าสนใจ ตอนนี้ Doom อยู่ในมือ Microsoft เช่นเดียวกับ Quake, StarCraft, WarCraft, Overwatch, เกมผจญภัยทั้งหมดของ Infocom และ Sierra รวมถึง Halo ด้วย Microsoft พยายามจะครองทรัพย์สินทางปัญญาของเกมพีซีส่วนใหญ่มาตั้งแต่ปี 1996 ดังนั้นก็แทบจะบรรลุเป้าหมายนั้นแล้ว
ภาคปี 2016 เป็นเกม FPS เล่นคนเดียวที่ดีที่สุดที่ฉันเคยเล่นมา มีแค่ Titan Fall 2 เท่านั้นที่พอจะเทียบกันได้
สงสัยว่าบนฮาร์ดแวร์มีฟีเจอร์สำหรับ trap overflow หรือไม่ เคยอ่านบทความเกี่ยวกับการทำงานของเอนจิน Doom แล้วเห็นว่าตัวแปรติดตามเดโมจะเพิ่มขึ้นต่อไปแม้จะเริ่มเดโมถัดไปแล้วก็ตาม และตัวแปรนี้ถูกนำไปเทียบกับตัวแปรอีกตัวที่เก็บค่าก่อนหน้าไว้ เลยสงสัยว่าทำไมเกมจริงถึงเกิดแครช
ต้องขอบคุณที่รู้อยู่แล้วว่าต้นเหตุของบั๊กคืออะไร ไม่อย่างนั้นอาจปล่อยไว้ 2.5 ปีแล้วเพิ่งมานึกได้ว่า "บ้าเอ๊ย ลืมเปิด debug log" ก็ได้
DOOM แครชก่อน Windows CE เสียอีก
สิ่งที่น่าทึ่งที่สุดสำหรับฉันคือแอปพลิเคชันบน PDA รันต่อเนื่องได้ตั้ง 2.5 ปี ฉันสงสัยมากว่าบนฮาร์ดแวร์สมัยใหม่ที่ตัดอินเทอร์เน็ตออกจะยังทำอะไรแบบนี้ได้หรือเปล่า
เป็นสถิติที่น่าทึ่งจริง ๆ
ดูเหมือนเว็บไซต์จะล่มเพราะคนเข้าเยอะเกินไป เลยขอแปะลิงก์ archive.org ไว้ ลิงก์สำเนาจาก archive.org น่าเสียดายที่รูปแบบของเว็บเก็บไว้ไม่ครบ แต่ตัวข้อความยังอยู่
ปี 2038 น่าจะเป็นปีที่น่าสนใจมาก
หลายคนมองข้ามปัญหา NTP ในปี 2036 ไป ตอนนั้นแหละงานเลี้ยงของจริงจะเริ่ม
ปี 2038 ให้ความรู้สึกใกล้กว่ายุค y2k มาก
เหลือเวลาอีก 13 ปีในการอัปเกรดเป็น int แบบ 64 บิต หรือเปลี่ยน time_t เป็นชนิด long long อุปกรณ์ฝังตัวจำนวนมากหรือระบบปิดที่เลิกซัพพอร์ตไปแล้วคงต้องได้รับความใส่ใจเป็นพิเศษ OpenFirmware ใน SunServer 600MP เครื่องเก่าที่ฉันเคยใช้ก็มีปัญหาแบบเดียวกัน โชคดีที่ตอนนี้มันไม่ใช่เรื่องที่ต้องกังวลแล้ว
การแก้ปัญหานั้นคือแผนเกษียณของฉัน
การทดสอบระดับนี้เป็นสิ่งที่ฉันไม่คิดว่าจะมีเทสเตอร์คนไหนที่รู้จักทำกัน แม้แต่ในระบบที่ฉันทำงานอยู่ แค่เมื่อวานก็ยังต้องรอเกิน 5 รอบเพื่อเช็กการจัดการข้อผิดพลาดหลัง timeout 30 วินาที ซึ่งน่าหงุดหงิดมาก
ครั้งหนึ่ง Windows NT 4 ก็เคยมีบั๊กคล้าย ๆ กัน มันเป็นตัวนับความละเอียดสูงที่ใช้วัด uptime ของระบบ ก่อน Service Pack 3 (หรือ 2) เราตั้ง scheduler ให้รีบูตเครื่องทุกวันที่ 1 ของเดือน เพราะถ้าไม่ทำ ระบบจะล่มหลัง uptime ประมาณ 42 วัน แปลว่าแม้แต่ Microsoft เองก็ไม่ได้คิดว่าระบบปฏิบัติการเซิร์ฟเวอร์จะรันต่อเนื่องได้นานขนาดนั้น
ขอชื่นชมทีม id Software อีกครั้ง ถ้าพัฒนาแบบทั่วไปในสมัยนี้ เกมคงตายเพราะ memory fragmentation หรือ memory leak ไปก่อนจะอยู่ถึง 2 ปีเสียอีก