2 คะแนน โดย GN⁺ 22 일 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • มีการพบบั๊ก การไม่ปลดล็อกทรัพยากร ในโค้ด Apollo Guidance Computer(AGC) ซึ่งเคยถูกมองว่าเกือบสมบูรณ์แบบมาตลอด 57 ปี
  • ทีม JUXT ใช้ภาษาเขียนสเปก AI Allium และ Claude วิเคราะห์แอสเซมบลี 130,000 บรรทัด และระบุข้อบกพร่องที่วิธีตรวจสอบแบบเดิมไม่สามารถเผยให้เห็นได้
  • ใน เส้นทางการจบการทำงานแบบผิดปกติ (BADEND) ของรูทีนควบคุมไจโร มีการไม่ปลดล็อก LGYRO ทำให้ฟังก์ชันที่เกี่ยวข้องกับไจโรทั้งหมดอาจหยุดทำงานในภายหลัง
  • หากระหว่างภารกิจจริงในวงโคจรรอบดวงจันทร์มีการกด สวิตช์ Cage ผิดพลาด งานจัดแนว Program 52 อาจหยุดลง และ Collins อาจเข้าใจผิดว่าเป็นความขัดข้องของฮาร์ดแวร์
  • กรณีนี้แสดงให้เห็นว่าการวิเคราะห์แบบ อิงสเปกเชิงพฤติกรรม เป็นวิธีที่ทรงพลังในการค้นหาข้อบกพร่องใหม่ ๆ แม้ในโค้ดเก่า

ข้อบกพร่องแฝงที่ค้นพบในคอมพิวเตอร์นำทางของ Apollo 11

  • Apollo Guidance Computer(AGC) เป็นหนึ่งในโค้ดเบสที่ถูกตรวจสอบอย่างละเอียดที่สุดในประวัติศาสตร์ และได้รับการวิเคราะห์โดยนักพัฒนาและนักวิจัยจำนวนมาก
    • อย่างไรก็ตาม มีการยืนยันว่ามี บั๊กการไม่ปลดล็อกทรัพยากร ในโค้ดควบคุมไจโรที่ไม่ถูกค้นพบมานาน 57 ปี
    • ปัญหาคือในเส้นทางข้อผิดพลาดไม่มีการปลดล็อก ทำให้ความสามารถในการจัดแนวแพลตฟอร์มนำทางใหม่ถูกปิดใช้งาน
  • ทีม JUXT ใช้ภาษาเขียนสเปกที่ขับเคลื่อนด้วย AI อย่าง Allium และ Claude แปลงแอสเซมบลี AGC 130,000 บรรทัดให้เป็นสเปกเชิงพฤติกรรม 12,500 บรรทัด
    • ดึงสเปกจากโค้ดโดยตรงเพื่อสร้างแบบจำลองทุกเส้นทางของการได้มาและการปล่อยทรัพยากร
    • ในกระบวนการนี้จึงพบข้อบกพร่องที่การอ่านโค้ดหรือการจำลองการทำงานแบบเดิมไม่สามารถเปิดเผยได้

โครงสร้างโค้ดและแนวทางการวิเคราะห์

  • ซอร์สของ AGC ถูกเผยแพร่ในปี 2003 เมื่อ Ron Burkey และอาสาสมัครถอดความจากเอกสารพิมพ์ของ MIT Instrumentation Laboratory ด้วยมือ
    • ในปี 2016 มีการเผยแพร่คลัง GitHub ของ Chris Garry ทำให้นักพัฒนาทั่วโลกได้ศึกษารหัสแอสเซมบลีของเครื่องที่มี RAM 2KB และ CPU 1MHz
  • โปรแกรมถูกเก็บไว้ใน core rope memory ขนาด 74KB โดยใช้การร้อยสายทองแดงผ่านแกนแม่เหล็กด้วยมือเพื่อแทนค่า 1 และ 0
    • ช่างเทคนิคหญิงที่ทำงานนี้ถูกเรียกว่า “Little Old Ladies” และหน่วยความจำนี้จึงถูกเรียกว่า LOL memory
  • จนถึงตอนนี้ยังไม่มีบันทึกว่ามีการทำ formal verification, model checking, static analysis กับ AGC
    • การตรวจสอบส่วนใหญ่เน้นที่การอ่านโค้ด การจำลองการทำงาน และการยืนยันความถูกต้องของการถอดความ
  • JUXT เขียนสเปกเชิงพฤติกรรมของซับซิสเต็ม IMU(Inertial Measurement Unit) ด้วย Allium
    • โดยสร้างแบบจำลอง จังหวะการได้มาและการปล่อย ของทรัพยากรที่ใช้ร่วมกันแต่ละตัวเพื่อระบุข้อบกพร่อง

การไม่ปลดล็อกในรูทีนควบคุมไจโร

  • AGC จัดการ IMU ผ่านล็อกร่วมชื่อ LGYRO
    • เมื่อต้องจ่ายแรงบิดให้ไจโรจะมีการยึดล็อกไว้ และจะปลดเมื่อครบทั้งสามแกนแล้ว
    • เพื่อป้องกันไม่ให้สองรูทีนควบคุมฮาร์ดแวร์พร้อมกัน
  • แต่ใน เส้นทางการจบแบบผิดปกติ ไม่มีการปลดล็อก
    • ในการจบแบบปกติ รูทีน STRTGYR2 จะปลด LGYRO แต่หากเกิด ‘Caging’ (การล็อกทางกายภาพเพื่อปกป้องไจโร) จะหลุดไปยังรูทีน BADEND
    • ใน BADEND ขาดคำสั่ง CAF ZERO และ TS LGYRO สองคำสั่ง (รวม 4 ไบต์) ทำให้ล็อกค้างอยู่
  • เมื่อ LGYRO ไม่ถูกปลด รูทีนจ่ายแรงบิดไจโรทั้งหมดหลังจากนั้นจะค้างรอการปลดล็อก
    • ทั้งการจัดแนวละเอียด การชดเชยดริฟต์ และการจ่ายแรงบิดแบบแมนนวล รวมถึงฟังก์ชันที่เกี่ยวข้องกับไจโรทั้งหมดจะหยุดลง

ผลกระทบที่อาจเกิดขึ้นขณะอยู่ด้านไกลของดวงจันทร์

  • วันที่ 21 กรกฎาคม 1969 Michael Collins ได้รัน Program 52 (โปรแกรมจัดแนวด้วยการสังเกตดาว) เป็นระยะ ๆ ระหว่างอยู่ในวงโคจรรอบดวงจันทร์
    • หากแพลตฟอร์มเกิดดริฟต์ ก็มีความเสี่ยงที่ทิศทางของเครื่องยนต์สำหรับเดินทางกลับจะคลาดเคลื่อน
  • หากระหว่างการจ่ายแรงบิดมีการกด สวิตช์ Cage ผิดพลาดจนเข้าสู่เส้นทาง BADEND ก็เป็นไปได้ว่า LGYRO จะไม่ถูกปลดและทำให้ P52 หลังจากนั้นทั้งหมดหยุดทำงาน
    • DSKY (จอแสดงผลและคีย์บอร์ด) จะรับอินพุตได้แต่ไม่ตอบสนอง
    • ฟังก์ชันอื่นยังทำงานปกติ ดังนั้น Collins อาจเข้าใจผิดว่าเป็นความขัดข้องของฮาร์ดแวร์
  • หากมีการรีสตาร์ต (hard reset) ปัญหาก็จะถูกแก้ไข แต่จากประสบการณ์ สัญญาณเตือน 1202 ระหว่างการลงจอดบนดวงจันทร์ การตัดสินใจรีเซ็ตทันทีคงไม่ใช่เรื่องง่าย

การออกแบบเชิงป้องกันของระบบเดิมและข้อจำกัด

  • ทีม MIT ที่นำโดย Margaret Hamilton ได้นำแนวคิดพื้นฐานของวิศวกรรมซอฟต์แวร์สมัยใหม่มาใช้ เช่น การจัดตารางตามลำดับความสำคัญ การทำงานหลายงานแบบอะซิงโครนัส และการป้องกันการรีสตาร์ต
    • ด้วยการออกแบบนี้จึงยังสามารถลงจอดได้แม้อยู่ระหว่างสัญญาณเตือน 1202
  • ข้อบกพร่องสำคัญส่วนใหญ่มักเป็น ข้อผิดพลาดในสเปก และมีกรณีที่ Don Eyles บันทึกไว้ว่า การขาดการซิงก์เฟสระหว่างฮาร์ดแวร์ทำให้ภาระ CPU เพิ่มขึ้น
  • ข้อบกพร่องครั้งนี้ก็มีโครงสร้างคล้ายกัน
    • BADEND เป็นรูทีนจบการทำงานทั่วไปสำหรับการสลับโหมดของ IMU จึงปล่อยทรัพยากรร่วมอย่าง MODECADR แต่ไม่ได้จัดการ LGYRO
    • เนื่องจากลอจิกการรีสตาร์ตจะรีเซ็ต LGYRO ปัญหาจึงถูกกู้คืนได้ระหว่างการทดสอบและซ่อนข้อบกพร่องนี้ไว้
  • แต่ใน สถานการณ์จริงที่ไม่มีการรีสตาร์ต ไจโรอาจค้างอยู่ในสถานะถูกล็อกถาวรได้

กระบวนการค้นหาข้อบกพร่องด้วย Allium

  • สเปกของ Allium สร้างแบบจำลอง วงจรชีวิต (lifecycle) ของทรัพยากรแต่ละชนิด
    • ฟิลด์ gyros_busy ใช้แทน LGYRO โดยกฎ GyroTorque กำหนดการยึดล็อก และกฎ GyroTorqueBusy กำหนดสถานะรอเมื่อมีการล็อกอยู่แล้ว
  • สเปกระบุข้อบังคับว่า “เมื่อล็อกกลายเป็น true แล้ว จะต้องกลับมาเป็น false ในภายหลังเสมอ”
    • เมื่อ Claude ติดตามทุกเส้นทาง จึงพบว่าในเส้นทางปกติ (STRTGYR2) มีการปลดล็อก แต่ในเส้นทางข้อผิดพลาด (BADEND) ไม่มี
  • แนวทางแบบอิงสเปกตรวจสอบไม่ใช่ว่าโค้ด ทำอะไรอยู่ แต่เป็นว่า ควรทำอะไร
    • การทดสอบยืนยันพฤติกรรมปัจจุบันของโค้ด แต่สเปกใช้ตรวจสอบพฤติกรรมที่ตั้งใจไว้
  • สเปก Allium และโค้ดสำหรับทำซ้ำบั๊กถูกเผยแพร่บน GitHub

นัยสมัยใหม่และบทเรียน

  • ในเวลานั้น โปรแกรมเมอร์ต้องปลดล็อกด้วยคำสั่ง CAF ZERO และ TS LGYRO ด้วยตนเอง
    • ต้องจำทุกเส้นทางของการทำงานและแทรกโค้ดปลดล็อกด้วยมือ
  • ภาษาโปรแกรมสมัยใหม่ป้องกัน ปัญหาการไม่ปล่อยทรัพยากร ลักษณะนี้ในเชิงโครงสร้าง
    • เช่น defer ของ Go, try-with-resources ของ Java, with ของ Python และ ระบบ ownership ของ Rust ที่ช่วยรับประกันการปล่อยโดยอัตโนมัติ
  • ถึงอย่างนั้น ข้อบกพร่องประเภท CWE-772 (การไม่ปล่อยทรัพยากร) ก็ยังคงมีอยู่
    • การเชื่อมต่อฐานข้อมูล, distributed lock, file handle และลำดับการปิดระบบโครงสร้างพื้นฐาน ยังเป็นความรับผิดชอบของโปรแกรมเมอร์อยู่ดี
  • แม้ภารกิจ Apollo ทั้งหมดจะกลับมาได้อย่างปลอดภัย แต่ข้อบกพร่องนี้ยังคงอยู่ในซอฟต์แวร์ COMANCHE(ยานบังคับการ) และ LUMINARY(ยานลงจอดบนดวงจันทร์) โดยไม่ได้รับการแก้ไข
  • ข้อบกพร่องที่ซ่อนอยู่มา 57 ปีนี้เป็นตัวอย่างที่แสดงถึงความสำคัญของ การวิเคราะห์แบบอิงสเปกเชิงพฤติกรรม

1 ความคิดเห็น

 
GN⁺ 22 일 전
ความเห็นบน Hacker News
  • ผมคือ Mike Stewart เป็นผู้นำโครงการฟื้นฟู AGC บน ช่อง CuriousMarc และเป็นผู้ดูแลร่วมของ VirtualAGC
    บั๊กที่พูดถึงครั้งนี้เป็น ข้อบกพร่องของซอฟต์แวร์ AGC ที่มีอยู่จริง แต่ไม่ได้ถูกปล่อยทิ้งไว้ตลอดอายุของโปรแกรมทั้งหมด
    มันถูกพบระหว่างการทดสอบระยะที่ 3 ของ SATANCHE และถูกบันทึกไว้เป็น L-1D-02 จากนั้นได้รับการแก้ไขระหว่าง Apollo 14 กับ 15
    สามารถดูรายงานที่เกี่ยวข้องได้ที่ เอกสาร ibiblio 1 และ เอกสาร 2
    การแก้ไขไม่ได้เป็นแค่การเพิ่มสองบรรทัดเพื่อทำให้ LGYRO เป็น 0 เท่านั้น แต่ยังรวมถึง การปรับโครงสร้างโค้ด และลอจิกสำหรับปลุกงานที่ค้างรออยู่ด้วย ถ้าเทียบโค้ดของ Apollo 14 และ 15 (โค้ด Apollo 14, โค้ด Apollo 15) ก็จะเห็นความต่าง
    มันไม่ใช่บั๊กที่เกิดขึ้นแบบเงียบ ๆ ตามที่บทความอธิบายไว้ LGYRO ถูกรีเซ็ตใน STARTSB2 ด้วย ซึ่งจะรันทุกครั้งที่มีการสลับโปรแกรมและช่วยเคลียร์ปัญหาโดยอัตโนมัติ ดังนั้นในความเป็นจริงมันจึงเกิดขึ้นได้ยากมาก และจะเกิดเฉพาะตอนทำ การทำงานของ torque ระหว่าง BADEND เท่านั้น
    ถ้าบั๊กค้างอยู่ต่อไป งานหลายตัวจะสะสมและสุดท้ายทำให้เกิดข้อผิดพลาด 31202 (เวอร์ชันถัดจาก 1202) ปัญหานี้ถูกค้นพบก่อนเที่ยวบิน Apollo 14 และมีการเพิ่มขั้นตอนกู้คืนไว้ใน Apollo 14 Program Notes
    อีกอย่าง แม้จะมีการบอกว่า Ken Shirriff เป็นคนวิเคราะห์ระดับเกต แต่จริง ๆ แล้วผมเป็นคนทำส่วนใหญ่
    Virtual AGC ตรวจสอบความตรงกันแบบ ตรงกันระดับไบต์ กับ core rope dump ต้นฉบับได้ครบเพียงบางโปรแกรมเท่านั้น และยังทำกับทั้งชุดโปรแกรมไม่ได้ ซอร์สส่วนใหญ่ถูกกู้คืนจากฉบับพิมพ์หรือเช็กซัม
    Margaret Hamilton เป็น ‘rope mother’ ของ Comanche (ซอฟต์แวร์ยานบังคับการ) ส่วน Luminary (ยานลงจอดดวงจันทร์) เป็นความรับผิดชอบของ Jim Kernan สามารถยืนยันได้จาก ผังองค์กรปี 1969
    ตอนเกิดสัญญาณเตือน 1202 นั้น AGC ไม่ได้ถูกออกแบบมาให้ตัดงานลำดับความสำคัญต่ำออก ตรงกันข้าม การนำร่อนลงจอดกลับเป็น งานลำดับความสำคัญต่ำที่สุด ขณะที่การควบคุมเสาอากาศและการอัปเดตหน้าจอมีลำดับสูงกว่า เอกสารนี้ สรุปลำดับความสำคัญของแต่ละงานไว้
    สุดท้าย สาเหตุของสัญญาณเตือน 1202 ไม่ใช่ความต่างของเฟส แต่เป็น ความต่างของแรงดันไฟฟ้า (28V vs 15V) ซึ่งได้รับการยืนยันจากการทดสอบฮาร์ดแวร์จริง วิดีโอการทดลองที่เกี่ยวข้องดูได้ที่ ลิงก์ YouTube

    • ผมรอคอมเมนต์ของคุณอยู่เลย ขอบคุณที่มาแชร์ รายละเอียดทางประวัติศาสตร์ ที่น่าทึ่งจริง ๆ
    • แม้หน้าแรกจะเปลี่ยนไปคุยเรื่องอื่นแล้ว แต่เนื้อหานี้คือ ข้อมูลล้ำค่า จริง ๆ ขอบคุณที่สละเวลามาเขียน
  • ถ้าคุณสนใจ Apollo AGC ขอแนะนำให้ดู ช่อง YouTube CuriousMarc อย่างยิ่ง ทีมที่เก่งมากทางเทคนิคได้บันทึกกระบวนการฟื้นฟูและวิเคราะห์ชิ้นส่วนต่าง ๆ ของ AGC เอาไว้
    ส่วนที่น่าสนใจเป็นพิเศษคือ การตีความสัญญาณเตือน 1202 ใหม่ ซึ่งโดยทั่วไปมักอธิบายว่าเป็นความผิดพลาดของเซ็นเซอร์ที่มองข้ามได้ แต่จริง ๆ แล้วในบางเงื่อนไขมันอาจร้ายแรงมาก

    • เพราะแบบนั้น ถ้ามองในวันนี้ก็อาจพูดได้ว่าการลองลงจอดแบบเดิมอีกครั้งยากขึ้นหรือก็ง่ายขึ้นก็ได้ เพราะเรารู้จัก โหมดความล้มเหลว มากกว่าสมัยนั้นมาก
    • “สิ่งที่อธิบายต่อสาธารณะ” กับ “สิ่งที่เข้าใจกันจริง ๆ” ไม่เหมือนกัน มีคำอธิบายแบบย่อให้เข้าใจง่ายเยอะ แต่ในหมู่ผู้เชี่ยวชาญมันเป็นสิ่งที่เข้าใจกันดีอยู่แล้ว
    • การพูดคุยของทีม CuriousMarc เกี่ยวกับการฟื้นฟู AGC ยังต่อเนื่องอยู่ใน เธรดนี้ ด้วย
  • ชิ้นส่วนโค้ดที่ผมชอบที่สุดคืออันนี้

    TC  BANKCALL  # TEMPORARY, I HOPE HOPE HOPE
    CADR STOPRATE  # TEMPORARY, I HOPE HOPE HOPE
    TC  DOWNFLAG  # PERMIT X-AXIS OVERRIDE
    

    ลิงก์ GitHub

    • โค้ดนี้ถูกพูดถึงใน The Codeless Code ด้วย
    • CADR ตรงนี้ไม่ได้เกี่ยวข้องกับ ฟังก์ชัน cadr ของ Lisp
    • มีใครอธิบายได้ไหมว่าทำไมโค้ดนี้ถึงน่าสนใจ
    • ผมจำได้ลาง ๆ ว่าเคยเห็นบทกวีเกี่ยวกับโค้ดนี้ใน XKCD แต่อาจจะจำผิดก็ได้
  • ผมสงสัยว่ามีการตรวจสอบหรือยืนยันไหมว่าบั๊กนี้มีอยู่จริง AI เก่งกับ การวิเคราะห์เชิงสำรวจ แบบนี้ แต่ก็ยังมี อัตราการแจ้งพลาด สูง
    ขึ้นอยู่กับบริบทด้วยว่ามันสำคัญหรือไม่สำคัญ และก็ยังมีบั๊กอีกมากที่ AI หาไม่เจอ
    ผมไม่มีความเชี่ยวชาญพอจะตรวจเองได้ แต่คิดว่าน่าสนใจมาก

    • จริง ๆ ก็ยังไม่ชัดด้วยซ้ำว่า AI เป็นคนพบบั๊กหรือเปล่า ในบทความบอกแค่ว่า “โมเดลมันในภาษาแบบ native ของ AI”
      แต่คำอธิบายเรื่อง การได้ล็อกและสถานการณ์ตอนล้มเหลว ก็ค่อนข้างน่าเชื่อถือทีเดียว
  • ที่พวกเขาหาบั๊กจริงเจอได้นั้นน่าสนใจ แต่ การทำให้เรื่องดูดราม่า ในบทความแทบจะเป็นเรื่องแต่ง
    เช่นการเอาศอกไปโดนสวิตช์ หรือการขยายความปัญหาที่รีเซ็ตก็แก้ได้ จุดพวกนี้ทำให้บทความดูเร้าอารมณ์แต่ความน่าเชื่อถือลดลง แถมยังมี สำนวนแบบที่ AI เขียน ยิ่งทำให้ขัดใจ

    • แน่นอนว่าสวิตช์นั้นเป็น สวิตช์ที่มีฝาครอบป้องกัน
      แต่ถ้าจะอธิบายบั๊กละเอียดอ่อนให้ผู้อ่านทั่วไปเข้าใจ ก็ต้องมี การเล่าเรื่อง อยู่บ้าง ถ้าเทคนิคเกินไปคนก็หมดความสนใจ ถ้าดราม่าเกินไปผู้เชี่ยวชาญก็จะวิจารณ์ ผมว่าการหาจุดสมดุลตรงนี้ยากมาก
  • ผมลองรัน โค้ดสำหรับทำซ้ำปัญหา (repro) ที่อยู่ในบทความด้วยตัวเองแล้ว
    ลิงก์ GitHub
    มันรันได้ก็จริง แต่ใน Phase 5 (สาธิต deadlock) เป็น เอาต์พุตปลอม ทั้งหมด คือไม่ได้รันอีมูเลเตอร์จริง แค่พิมพ์ผลลัพธ์ที่คาดว่าจะได้ออกมา
    เลยทำให้ผมส่ง PR ของตัวเอง เพื่อแก้ให้มันทำงานจริงบนอีมูเลเตอร์ และตรวจสอบด้วยว่าแพตช์สองบรรทัดนั้นแก้บั๊กได้จริงหรือไม่

    • ผมเห็น “โค้ดแบบ AI” ลักษณะนี้บ่อยมาก มันทำเหมือนใช้การพัฒนาแบบ test-driven แต่จริง ๆ คือ โค้ดปลอมที่แค่ทำให้เทสต์ผ่าน
      โค้ดที่ AI สร้างมักชอบหยุดที่จุด “ตอนนี้สมบูรณ์แบบแล้ว!” และคนที่เชื่อมันก็เอาไปปล่อยต่อทั้งอย่างนั้น นี่แหละคือปัญหาจริง
  • ตัวบทความเองก็น่าสนใจ แต่ให้ความรู้สึก ประดิษฐ์แบบเหมือน LLM เขียน ค่อนข้างแรง

    • สำหรับผมมันไม่ให้ความรู้สึกแบบ LLM เลย น่าจะเพราะสไตล์เหมือนบทความวิทยาศาสตร์มากกว่า
    • Juxt เขียนบทความดี ๆ มานานแล้ว และก็มีความเชี่ยวชาญเพียงพอ ดังนั้นผมจึงมองว่าบทความนี้ไม่น่าใช่งานที่ AI เขียน
    • อ้างอิงจาก การวิเคราะห์ของ Pangram บทความนี้ถูกตัดสินว่า มนุษย์เป็นผู้เขียน
    • แต่ในบทความอื่นของ Juxt มีชิ้นหนึ่งที่ ระบุชัดว่า Claude เป็นผู้เขียน จริง ๆ บทความนั้น บอกไว้ในย่อหน้าสุดท้าย
    • แถมในส่วนที่พูดถึง Rust กับล็อกก็ยัง ไม่ตรงกับข้อเท็จจริง ด้วย คอมเมนต์นี้ ได้ชี้ไว้
  • การที่ซอฟต์แวร์ที่พามนุษย์ไปดวงจันทร์ด้วยหน่วยความจำเพียง 4KB ยังมี บั๊กที่ไม่ถูกค้นพบ อยู่ แสดงให้เห็นว่าความซับซ้อนสามารถซ่อนอยู่ได้แม้ในโค้ดขนาดเล็ก

    • ยิ่งหน่วยความจำน้อย ความสัมพันธ์ระหว่างความยาวโค้ดกับอัตราบั๊กก็ยิ่งอ่อนลง ตรงกันข้าม การพยายาม บีบอัดความซับซ้อน ต่างหากที่ทำให้บั๊กเพิ่มขึ้น
    • คำพูดแบบนี้ฟังดูเหมือน วลีโหลที่กลวงเปล่า มากกว่า
  • การพูดว่า “ดึงสเปกออกมาจากโค้ด” เป็นการใช้คำผิด ควรกลับไปดูความหมายของ specification ใหม่

    • จริง ๆ แล้วมันหมายถึงแค่ การทำรีเวิร์สเอนจิเนียริง
  • ทั้งบทความและรีโพซิทอรีเป็น งานคุณภาพต่ำแบบลวก ๆ
    ถ้าดู ลิงก์รีโพซิทอรี จะเห็นว่ามันอ้างว่าเป็น “การทำซ้ำปัญหา” แต่ไม่ได้รันบั๊กจริงเลย แค่พิมพ์ ข้อความเอาต์พุตว่ามันน่าจะเป็นแบบนี้ ออกมาเท่านั้น