4 คะแนน โดย GN⁺ 2025-09-18 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ยืนยันการเกิดอาการ เกมแครช จาก 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 ความคิดเห็น

 
GN⁺ 2025-09-18
ความคิดเห็นจาก 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 แล้วเห็นว่าตัวแปรติดตามเดโมจะเพิ่มขึ้นต่อไปแม้จะเริ่มเดโมถัดไปแล้วก็ตาม และตัวแปรนี้ถูกนำไปเทียบกับตัวแปรอีกตัวที่เก็บค่าก่อนหน้าไว้ เลยสงสัยว่าทำไมเกมจริงถึงเกิดแครช

    • ในภาษา C นั้น signed overflow เป็น undefined behavior ดังนั้นผลลัพธ์จึงคาดเดาไม่ได้ แต่กรณีนี้ดูเหมือนจะเกิดแบบเดียวกันไม่ว่าจะเป็นแพลตฟอร์มหรือคอมไพเลอร์ไหน จึงน่าจะไม่ใช่ปัญหานั้น ตามที่บทความต้นฉบับ (TFA) บอกไว้ ตัวแปรนี้ถูกนำไปเทียบกับค่าก่อนหน้า และโค้ดถูกเขียนโดยไม่เคยคิดว่าสถานการณ์ new < old จะเกิดขึ้นได้ ทำให้บั๊กอย่างเช่นสแตกเสียหายเกิดขึ้นได้ง่าย C ยังมี undefined behavior แบบหน้าตาเฉยอีกหลายอย่าง เช่น ถ้าฟังก์ชันที่ไม่มีค่า return ไปถึงจุดที่ควรต้องคืนค่า มันก็จะทำงานแบบ undefined ไปเลย
  • ต้องขอบคุณที่รู้อยู่แล้วว่าต้นเหตุของบั๊กคืออะไร ไม่อย่างนั้นอาจปล่อยไว้ 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 เองก็ไม่ได้คิดว่าระบบปฏิบัติการเซิร์ฟเวอร์จะรันต่อเนื่องได้นานขนาดนั้น

    • หมายถึงปัญหาที่พูดถึงในลิงก์นี้ หรือเปล่า หรือว่า NT 4 มีบั๊กแยกอีกตัวหนึ่ง อยากรู้เหมือนกัน
  • ขอชื่นชมทีม id Software อีกครั้ง ถ้าพัฒนาแบบทั่วไปในสมัยนี้ เกมคงตายเพราะ memory fragmentation หรือ memory leak ไปก่อนจะอยู่ถึง 2 ปีเสียอีก