વિડ્થ ચેકને કારણે એક કાન્જી તૂટી ગઈ

એક નામ ટર્મિનલ ટેબલમાં દાખલ કરવામાં આવ્યું અને તે તૂટેલું બહાર આવ્યું. અટક 𠮷田 હતી.

પ્રથમ અક્ષર સામાન્ય 吉 નથી. તે 𠮷 (U+20BB7) છે. આ જાપાનીઝ કુટુંબના નામોમાં વપરાતું એક દુર્લભ સ્વરૂપ છે. કોલમમાં સમાવવા માટે ટેબલે સેલને ટ્રંકેટ (truncate) કરી દીધું. નામ આપવાને બદલે, તેણે એક તૂટેલો અક્ષર પ્રિન્ટ કર્યો. કાન્જી અડધી વહેંચાઈ ગઈ હતી.

આ બગ (bug) એક લાઇનના શોર્ટકટમાં હતો. કોડ દ્વારા સ્ટ્રિંગને ખરેખર ટ્રંકેટ કરતા પહેલા, ઇન્ડેક્સ દ્વારા કાપવી સુરક્ષિત છે કે નહીં તેનો નિર્ણય લેવામાં આવ્યો હતો. 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 બરાબર નથી, કોડ તૂટેલા શોર્ટકટથી બચી જાય છે. આ બગ ફક્ત દુર્લભ અક્ષરો અને ઇમોજી પર જ અસર કરે છે.

આને સુધારવા માટે, તમારે:

  • હાઈ સરોગેટ્સ (high surrogates) ધરાવતી સ્ટ્રિંગ્સને નકારવા માટે ફાસ્ટ પાથને ગાર્ડ (guard) કરો.
  • કોડ યુનિટ્સને બદલે આખા કોડ પોઈન્ટ્સ દ્વારા ટ્રિમ કરો.

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/