Ccmmutty logo
Commutty IT
0 pv3 min read

文字コードの闇 (U+3099/U+309A)

https://cdn.magicode.io/media/notebox/226c2b8b-b6e0-46b6-a9c0-a51850ea02ba.jpeg

これは何

渡されたファイル名がおかしく同一名称のファイルが存在していたためにファイルを取り違える事件が起きたのでその時の記録。

事象

ファイルシステムでは基本的に同じフォルダ名であったりファイル名(拡張子が異なる場合等は除く)が同じものは存在できません。
もし作ろうとした場合、Windowsだと以下のようなエラーが発生すると思います。
Fig.1 同一名称のフォルダ作成
しかし、ある方法をすると…?
Fig.2 同一名称のフォルダが存在する様子
存在できてしまっていますね。
以前ユーザー提供のファイルが上記のような状況になってしまったのでこの原理のお話。

種明かし

構成されている文字を調べる

Pythonのord関数を用いてコードポイント(文字や記号に割り当てられた一意の数値)を確認してみましょう。
str1 = '同じ名前のフォルダ'
str2 = '同じ名前のフォルダ'


len1, len2 = len(str1), len(str2)
max_len = max(len1, len2)

print(f"{'Char1':<6} {'Code1':<8} {'Char2':<6} {'Code2':<8} {'Diff':<6}")
print("-" * 40)

for i in range(max_len):
    char1 = str1[i] if i < len1 else ''
    char2 = str2[i] if i < len2 else ''
    code1 = ord(char1) if char1 else None
    code2 = ord(char2) if char2 else None
    diff = (code1 - code2) if code1 and code2 else None
    
    print(f"{char1:<6} {hex(code1) if code1 else '':<8} {char2:<6} {hex(code2) if code2 else '':<8} {diff if diff is not None else ''}")
上記の結果は以下の通り。
Char1  Code1    Char2  Code2    Diff  
----------------------------------------
同      0x540c   同      0x540c   0
じ      0x3058   じ      0x3058   0
名      0x540d   名      0x540d   0
前      0x524d   前      0x524d   0
の      0x306e   の      0x306e   0
フ      0x30d5   フ      0x30d5   0
ォ      0x30a9   ォ      0x30a9   0
ル      0x30eb   ル      0x30eb   0
ダ      0x30c0   タ      0x30bf   1
                ゙      0x3099   
最後になにかいますね。

ユニコード文字 U+3099/U+309A

ダ (0x30c0)
ダ (0x30bf + 0x3099)
上記の2つは一見同じに見えますが、一方は 0x30c0 と一文字分で「ダ」が構成されているのに対し、もう一方は 「タ + ゙ 」0x30bf + 0x3099 のように構成されており機械的には同一でないことがわかります。
なんでこんなことになったのかは知りませんがMacでファイルを作ったらこうなることがあるらしい。
→ 詳細はNFC/NFD問題で検索すると出てきます。
頭の片隅に入れておくと役に立つときがあるかもしれません。


  おしまい


ด็็็็็้้้้้็็็็้้้้้็็็็็้้้้้็็็็็้้้้้็็็็(・ω・)ด็็็็็้้้้้็็็็้้้้้็็็็็้้้้้็็็็็้้้้้็็็็

Discussion

コメントにはログインが必要です。