Apple กำลังเผชิญกับช่วงเวลาที่มีบั๊กมากมายในหลายเดือนที่ผ่านมา และตอนนี้เราก็ได้เจอบั๊กใหม่ที่รุนแรงในฟังก์ชันการเรนเดอร์ข้อความบน iPhone บั๊กนี้ถูกกระตุ้นโดยตัวอักษร Telugu เพียงตัวเดียว ซึ่งสามารถทำให้ iPhone เข้าสู่สถานะบูทลูปที่ไม่สามารถแก้ไขได้ เพียงแค่ได้รับการแจ้งเตือนที่มีตัวอักษรดังกล่าว มาดูกันว่าเหตุใดตัวอักษรเพียงตัวเดียวจึงสร้างปัญหาใหญ่โตกับ iOS ได้
หมายเหตุ: แก้ไขบั๊ก Telugu นี้มีใน iOS เวอร์ชันล่าสุด (11.2.6) หากตัวอักษร Telugu ทำให้แอปหรืออุปกรณ์ของคุณล็อก ให้กู้คืน iPhone ผ่าน iTunes และอัปเดตเป็น iOS เวอร์ชันล่าสุด หาก iPhone ค้างที่บูทลูป อาจต้องเข้าโหมด Device Firmware Update (DFU) เพื่อให้ iTunes จดจำได้ เมื่อเสร็จแล้ว ให้กู้คืนอุปกรณ์จากแบ็กอัปล่าสุด ซึ่งหวังว่าคุณได้สร้างไว้แล้ว
Telugu คืออะไร?
Telugu เป็นภาษาที่พูดและเขียนในบางส่วนของอินเดีย โดยเฉพาะรัฐอานดร้า ปราเดช เทลังกานา และเมืองยานาม ในทำนองเดียวกับภาษาที่ใช้สคริปต์หลายภาษา เช่น อาหรับ และสคริปต์บราหมีอื่นๆ Telugu ใช้คุณสมบัติพิเศษของชุดอักขระ Unicode เพื่อแสดงตัวอักษรบนหน้าจอคอมพิวเตอร์
ในขณะที่ตัวอักษรละตินส่วนใหญ่ถูกแทนด้วย Unicode code point 8 บิตเพียงตัวเดียวเพื่อความเข้ากันได้กับ ASCII (เช่น ตัวอักษร A อยู่ที่ Unicode code point U+0041 ซึ่งแสดงในไบนารีเป็น 01000001) ภาษาที่เขียนด้วยสคริปต์หรือตัวอักษรที่ไม่ใช่ละติน มักรวม code point Unicode มากกว่าหนึ่งตัวเพื่อแทนตัวอักษรของพวกเขา
สิ่งนี้เป็นจริงโดยเฉพาะกับภาษาเช่น Telugu ที่รวมตัวอักษรของภาษาเป็นกลุ่ม (cluster) ต่างจากลิเกเจอร์ (ligature) แบบสวยงามของภาษาอังกฤษ การเชื่อมต่อระหว่างตัวอักษร Telugu แต่ละตัวมีความสำคัญทางภาษาศาสตร์ เพื่อรองรับสิ่งนี้ Unicode จึงมีระบบซับซ้อนในการผนวกอักขระ ซึ่งแต่ละตัวมี code point ของตัวเอง เข้าด้วยกัน
ด้วยจำนวน code point Unicode ที่มหาศาล สร้างความหลากหลายได้เกือบอนันต์ จุดเหล่านี้รวมกันเพื่อเรนเดอร์ให้ได้ตัวอักษรที่อ่านออก Unicode จึงไม่ต้องมี code point สำหรับคำ Telugu ทุกคำที่เป็นไปได้ แทนที่จะเป็นเช่นนั้น Unicode รวมพยัญชนะ สระ และเครื่องหมายวรรคตอน (virama) ของ Telugu เข้าด้วยกัน เพื่อสร้างคำที่แสดงเหมือนตัวอักษรเดียว สิ่งเดียวกันนี้ใช้ได้กับภาษาอื่นที่มีกฎออร์โธกราฟิกสำหรับลิเกเจอร์ เช่น ภาษาอาหรับ
สาเหตุของการแครชคืออะไร?
ปัญหานี้ดูเหมือนจะเกี่ยวข้องกับ Zero Width Non-Joiner (ZWNJ) ที่ code point U+200C ZWNJ ขอให้ตัวอักษรที่อยู่ติดกันสองตัว เรนเดอร์โดยไม่มีลิเกเจอร์ทั่วไปของพวกเขา ในภาษาอังกฤษ ZWNJ ทำให้ตัวอักษร ff ไม่ถูกพิมพ์ด้วยการเชื่อมต่อมาตรฐาน แทนที่จะแยก f แต่ละตัวออกมา แต่เมื่อรวมกับชุด code point Telugu 4 ตัวเฉพาะ (ซึ่งทั้งหมดควรจะรวมเป็นกลุ่มเดียว) iOS ไม่สามารถแสดงผลได้อย่างถูกต้อง โจมตี
บางคนערערว่าแบบอักษร San Francisco ของ Apple ไม่สามารถแสดงตัวอักษรนี้ได้ ส่วนบางคนกล่าวว่ากระบวนการเรนเดอร์เฉพาะที่ Apple ใช้เป็นตัวเป็นเหตุ ไม่ว่าสาเหตุที่แน่นอนจะเป็นอย่างไร การพยายามเรนเดอร์ตัวอักษรนี้ทำให้เกิดการแครชอย่างรุนแรงกับทุกอย่างที่กำลังเรนเดอร์อยู่ จาก Messages, WhatsApp ไปจนถึง Springboard Unicode code point ที่ประกอบเป็นตัวอักษรนี้ (“gya” หมายถึง “ความรู้”) มีดังนี้:
U+0C1Cja (
)U+0C4Dvirama หรือเครื่องหมายวรรคตอน (
)U+0C1Enya (
)U+200Czero width non-joinersU+0C3Eaa (
)
แต่เราไม่สามารถ 탓 ZWNJ เพียงอย่างเดียวได้ มันยังถูกใช้ในอีโมจิครอบครัว (????) ที่ไม่เป็นอันตรายโดยไม่มีปัญหาใดๆ ดูเหมือนจะเป็นการรวมกันเฉพาะของ code point บางตัวและ ZWNJ เพิ่มเติมคือ ZWNJ ไม่มีผลต่อการเรนเดอร์กลุ่ม Telugu นี้เลย หรือว่าไม่ควรจะอยู่ที่นั่นตั้งแต่แรก
ปัญหาสคริปต์บราหมีอื่นๆ
Telugu ไม่ใช่ภาษาเดียวที่มีปัญหานี้ Bengali และ Devanagari ที่ใช้ Unicode ในลักษณะคล้ายกันสำหรับสคริปต์บราหมี ก็มีปัญหาเดียวกัน Manish Goregaokar เขียนบล็อกโพสต์ที่น่าสนใจและละเอียดซึ่งแยกกรณีการแครชออกมาเป็นรายละเอียด:
ลำดับใดๆ
<consonant1, virama, consonant2, ZWNJ, vowel>ใน Devanagari, Bengali และ Telugu โดยที่:1.
consonant2เป็น suffix-joining (pstf/vatu)
2.consonant1ไม่ใช่ตัวอักษรที่สร้าง reph
3.vowelไม่มีคอมโพเนนต์ glyph สองชิ้น
สรุป: ทำไม Apple จึงไม่จับบั๊กนี้ได้?
เพื่อเข้าใจว่าบั๊กนี้หลุดออกมาได้อย่างไร คุณต้องตั้งตัวเองในตำแหน่งของ Apple แน่นอนว่าการรวมตัวอักษรนี้ไม่ใช่คำที่แปลกใหม่มากในภาษา Telugu แต iPhone รองรับภาษาหลายสิบภาษา มีการรวมกันของ Unicode ที่เป็นไปได้เป็นพันล้านรูปแบบ ด้วยความหลากหลายมากมาย การทดสอบบั๊ก Unicode อย่างมีความหมายก่อนการปล่อยตัวจะทำให้การอัปเดตซอฟต์แวร์ปกติเป็นไปไม่ได้เกือบ
อย่างไรก็ตาม ข้อผิดพลาดนี้ไม่ควรทำความเสียหายมากขนาดนี้ โทรศัพท์ไม่ควรถูกทำให้อิฐ (bricked) เพียงแค่เนื้อหาข้อความ แม้มุมมองย้อนหลังจะชัดเจน แต่ดูเหมือนว่าการเรนเดอร์ตัวอักษรเป็นกล่องเครื่องหมายคำถาม () จะดีกว่าการแครช Springboard มาก