เหตุการณ์ที่ `malloc` ทำให้ JPGLoader ของ Serenity พัง หรือ: เคล็ดลับถูกรางวัลลอตเตอรี่ (2021)
(sin-ack.github.io)-
เหตุผลที่
mallocทำให้ JPGLoader ของ SerenityOS พัง -
ตรวจสอบบั๊กที่ทำให้สีแสดงผลผิดพลาดเมื่อถอดรหัสภาพ JPG ใน SerenityOS
- ตอนแรกดูเหมือนเป็นความสับสนระหว่าง RGB กับ BGR แต่แม้จะแก้โค้ดแล้ว ปัญหาก็ยังไม่หาย
-
การไล่หาปัญหาด้วย bisecting
- เริ่มค้นหาสาเหตุของปัญหาด้วยการทำ bisecting กับคอมมิตล่าสุด 1000 รายการ
- SerenityOS ใช้ไลบรารีมาตรฐานของตัวเองชื่อ AK ซึ่งคล้ายกับ STL ของ C++ แต่มีความอ่านง่ายกว่า
- การเปลี่ยนแปลงใน AK ส่งผลต่อทั้งระบบปฏิบัติการ ทำให้ใช้เวลาบิลด์นาน
-
ผลลัพธ์ของการ bisect
- พบคอมมิตที่เป็นต้นเหตุของปัญหา: คอมมิตที่เพิ่มการทำงานของ
malloc_good_size() - คอมมิตนี้เพิ่มความสามารถในการปรับขนาดการจัดสรรหน่วยความจำให้เหมาะสมเพื่อลดการสิ้นเปลืองหน่วยความจำ
- พบคอมมิตที่เป็นต้นเหตุของปัญหา: คอมมิตที่เพิ่มการทำงานของ
-
การค้นพบที่น่าประหลาดใจ
- ตรวจสอบความเป็นไปได้ที่
HashTableและVectorจะเป็นต้นเหตุของปัญหา - หลังจากเปลี่ยนความจุของ
HashTableปัญหาก็หายไป
- ตรวจสอบความเป็นไปได้ที่
-
การวนซ้ำคอมโพเนนต์แบบอนุกรมที่ไม่กำหนดแน่นอน
- JPGLoader จัดเก็บคอมโพเนนต์ของไฟล์ JPG ไว้ใน
HashTableและนำมาใช้แบบวนซ้ำ - ลำดับของคอมโพเนนต์ไม่แน่นอน จึงทำให้เกิดปัญหา
- JPGLoader จัดเก็บคอมโพเนนต์ของไฟล์ JPG ไว้ใน
-
สาเหตุของบั๊ก
- มีการเก็บอ็อบเจ็กต์ที่ต้องการลำดับไว้ใน
HashTableและใช้ iterator เริ่มต้น - ค่าแฮชของ ID คอมโพเนนต์บังเอิญถูกจัดเรียงเป็นลำดับที่ถูกต้องพอดี
- เมื่อขนาดของ
HashTableเปลี่ยน ลำดับก็เปลี่ยนตามและทำให้เกิดปัญหา
- มีการเก็บอ็อบเจ็กต์ที่ต้องการลำดับไว้ใน
-
วิธีแก้
- แก้ไขให้ JPGLoader วนซ้ำคอมโพเนนต์แบบกำหนดแน่นอนได้
- ใช้โครงสร้างข้อมูลที่รับประกันลำดับแทน
HashTable
-
ข้อคิดส่งท้าย
- ปัญหาที่ดูเรียบง่ายก็สามารถเผยให้เห็นความผิดพลาดครั้งใหญ่ได้
- แก้ปัญหาที่ต้นตอเพื่อป้องกันไม่ให้เกิดซ้ำ
-
คำขอบคุณ
- ขอบคุณเพื่อนร่วมงานที่ช่วยในการดีบัก
- ได้เรียนรู้อะไรมากมายจากกระบวนการค้นหาและแก้บั๊ก
สรุปของ GN⁺
- บทความนี้กล่าวถึงกระบวนการติดตามและแก้ไขบั๊กการถอดรหัสภาพ JPG ที่เกิดขึ้นใน SerenityOS
- ปัญหาเกิดจากลำดับที่ไม่แน่นอนของ
HashTableและได้รับการแก้ไขด้วยการเปลี่ยนให้เป็นลำดับที่กำหนดแน่นอน - บทความนี้แสดงให้เห็นถึงความสำคัญและความซับซ้อนของกระบวนการดีบักซอฟต์แวร์ได้อย่างชัดเจน
- โปรเจ็กต์ที่มีฟังก์ชันคล้ายกัน ได้แก่
libjpegของ Linux เป็นต้น
ยังไม่มีความคิดเห็น