ایک چوڑائی کی جانچ (Width Check) نے ایک کانجی (Kanji) کو توڑ دیا

ایک نام ٹرمینل ٹیبل میں داخل ہوا اور ٹوٹا ہوا نکلا۔ خاندانی نام 𠮷田 تھا۔

پہلا حرف عام 吉 نہیں ہے۔ یہ 𠮷 (U+20BB7) ہے۔ یہ ایک نایاب شکل ہے جو حقیقی جاپانی خاندانی ناموں میں استعمال ہوتی ہے۔ ٹیبل نے کالم میں فٹ کرنے کے لیے سیل (cell) کو چھوٹا (truncate) کر دیا۔ نام کے بجائے، اس نے ایک ٹوٹا ہوا حرف پرنٹ کر دیا۔ کانجی آدھی تقسیم ہو گئی تھی۔

یہ بگ (bug) ایک لائن کے شارٹ کٹ میں موجود تھا۔ کوڈ نے اصل میں اسے چھوٹا کرنے سے پہلے ہی یہ فیصلہ کر لیا کہ اسٹرنگ (string) کو انڈیکس (index) کے ذریعے کاٹنا محفوظ ہے۔ یہ منطق اس وجہ سے ناکام ہو گئی کیونکہ جاوا اسکرپٹ (JavaScript) اسٹرنگز کو ہینڈل کرنے کا ایک خاص طریقہ استعمال کرتا ہے۔

ایک JavaScript اسٹرنگ کی تین مختلف لمبائیاں ہوتی ہیں:

  • کوڈ یونٹ کی لمبائی (Code unit length): "𠮷".length 2 ہے۔ یہ UTF-16 یونٹس کو گنتی ہے۔
  • کوڈ پوائنٹ کی تعداد (Code point count): [..."𠮷"].length 1 ہے۔ یہ اصل حروف کو گنتی ہے۔
  • ڈسپلے کی چوڑائی (Display width): ٹرمینل میں یہ 2 کالم لیتا ہے۔

سادہ انگریزی متن کے لیے، یہ نمبرز ایک جیسے ہوتے ہیں۔ "abc" میں 3 یونٹس، 3 پوائنٹس اور 3 کالم ہوتے ہیں۔ زیادہ تر کوڈ یہ فرض کر لیتا ہے کہ یہ اتفاق ایک اصول ہے۔

حرف 𠮷 اس اصول کو توڑتا ہے۔ اس کے 2 کوڈ یونٹس اور 2 کالم ہیں۔ نمبرز تو ملتے ہیں، لیکن مختلف وجوہات کی بنا پر۔ کوڈ نے دیکھا کہ 2 برابر ہے 2 کے، اور اسٹرنگ کو انڈیکس کے ذریعے کاٹنے کے لیے ایک تیز راستہ (fast path) استعمال کیا۔

جب اس نے انڈیکس 3 پر اسٹرنگ کو کاٹا، تو اس نے پہلا مکمل حرف لیا اور دوسرے کا صرف آدھا حصہ لیا۔ اس سے ایک تنہا سرروگیٹ (surrogate) پیچھے رہ گیا۔ ٹرمینلز اسے ایک ٹوٹے ہوئے باکس کے طور پر دکھاتے ہیں۔

漢 جیسے عام جاپانی حروف محفوظ ہیں۔ ان کا 1 کوڈ یونٹ اور 2 کالم ہوتے ہیں۔ چونکہ 1 برابر نہیں ہے 2 کے، اس لیے کوڈ اس ٹوٹے ہوئے شارٹ کٹ سے بچ جاتا ہے۔ یہ بگ صرف نایاب حروف اور ایموجیز (emojis) پر اثر انداز ہوتا ہے۔

اسے ٹھیک کرنے کے لیے، آپ کو چاہیے کہ:

  • ہائی سرروگیٹس (high surrogates) والی اسٹرنگز کو مسترد کرنے کے لیے فاسٹ پاتھ (fast path) کی حفاظت کریں۔
  • کوڈ یونٹس کے بجائے مکمل کوڈ پوائنٹس کے ذریعے ٹرِم (trim) کریں۔

Array.from(str) کا استعمال اسے ٹھیک کر دیتا ہے کیونکہ یہ کوڈ پوائنٹ کے ذریعے عمل کرتا ہے۔ یہ حرف کو ایک مکمل یونٹ کے طور پر لیتا ہے۔

سبق سادہ ہے: کبھی بھی ایک یونٹ سے پیمائش نہ کریں اور دوسرے سے کٹائی نہ کریں۔ اگر آپ ڈسپلے کی چوڑائی ناپتے ہیں لیکن کوڈ یونٹ انڈیکس سے کاٹتے ہیں، تو آپ اپنے صارفین کا ڈیٹا خراب کر دیں گے۔

اپنے کوڈ کو کسی نایاب CJK حرف یا ایموجی کے ساتھ ٹیسٹ کریں۔ ASCII آپ کو یہ غلطیاں نہیں دکھائے گا۔ آپ کو وہ ان پٹ فراہم کرنا چاہیے جس سے آپ کا کوڈ ڈرتا ہے۔

Source: https://dev.to/greymothjp/a-width-check-said-the-string-was-safe-to-cut-it-split-a-kanji-in-half-4hjk

Optional learning community: https://greymoth-jp.github.io/cjk-failure-corpus/