要約

  • RFC 5137 は ASCII エスケープが必要なプロトコルを対象とし、UTF-8 を直接扱えるなら原則としてその方が望ましい。
  • 特別な理由がない限り、UTF-8 のオクテット列や UTF-16 のコード単位ではなく Unicode コードポイントを参照する。
  • 採用するプロトコルは、完全な構文とエスケープ導入文字を文字どおり表す方法を定義しなければならない。
  • 終端のデリミタは、四桁から六桁の十六進値と後続文字の境界を見える形にする。
  • \u だけでは構文を識別できず、C、Java、JSON などで似た表記が別の対象を指す。
  • インターネットプロトコルはサロゲートペアをエスケープ方式として使うべきではない。
  • 推奨例には、区切られた backslash-u 形式と、セミコロンを省略しない XML 数値文字参照がある。
  • コードポイントが復元できても、文字列全体の妥当性、正規化、識別子としての許可や等価性は証明されない。
  • セキュリティ検査をアンエスケープや正規化の誤った側で行えば、表記の違いが検査をすり抜ける。
  • 同じコードポイント、同じグリフ、同じ識別子、同じ主体はそれぞれ異なる主張である。
  • 入口のバイト、元の表記、スカラー値、正規化、比較キー、認可結果を分けて記録する必要がある。
  • 経営層は、構文の証拠が後段の意味や権限まで代表しないよう責任境界を定めるべきである。

一文字を巡ってログが食い違う理由

あるサービスは受信した ASCII 列を記録し、次のサービスはアンエスケープ後の値を記録し、ディレクトリは正規化後の名前を保存する。画面はフォントで整形された結果を表示する。どのログも「文字列」と呼ぶが、同じ観測対象ではない。

RFC 5137 は最初の変換を整理する。Unicode を直接運べず ASCII に埋め込む必要があるとき、シリアライズされた UTF-8 や UTF-16 の断片ではなく、コードポイントを参照する方がよい。人が Unicode 表を引きやすく、デバッグで一段余計に復号する必要もない。

ただし規格は、エスケープ対象の文字列がすでに妥当で合理的であると仮定する。一般的な Unicode 文字列処理、アカウント名の規則、正規化、画面表示を標準化する文書ではない。この限定は欠点ではなく、証拠の射程を明確にする設計である。

インシデント対応では「数値が一致した」ことを「正しい利用者に一致した」ことへ飛躍させてはならない。前者はパーサの受領書で、後者は文字列プロファイル、比較、内部 ID、認可ポリシーの受領書である。途中の変換が一つでも記録されていなければ、結論は再現できない。

オクテット列を文字の身代わりにしない

コードポイントは Unicode 符号空間の整数である。UTF-8 は一つから四つのオクテットへ、UTF-16 は一つまたは二つの 16 ビット単位へ変換する。オクテットをエスケープする形式は輸送形を表し、コードポイント形式は値を直接指す。

非 ASCII 文字の UTF-8 オクテットを個別に書けば、一文字が複数の数値片へ分かれる。読む側は符号化方式を知り、並びを復号して初めてコードポイントに到達する。途中の切断や順序違いも見落としやすい。RFC 5137 がコードポイントを既定にするのは、この隠れた工程を表面へ出すためである。

一方で、入口オクテットの保存は必要だ。最終値だけでは、受信 UTF-8 が正当だったか、過長表現や不正列を寛容に修復したかを判定できない。輸送境界では元のバイトと宣言された符号化、解釈境界ではスカラー値とエラーを残す。二つの受領書は競合せず、互いを補う。

UTF-16 の補助平面文字はさらに注意を要する。高位・低位サロゲートの二単位で一文字になるが、各半分は独立した Unicode スカラー値ではない。前段が半分ずつ許可し、後段が結合すると、検査時には存在しなかった文字が後から現れる。新しいインターネットプロトコルでサロゲートペアを避ける勧告には、この運用上の意味がある。

終端が見えることの価値

コードポイントは U+10FFFF まであるため、参照値は四、五、六桁になり得る。終端記号がなければ、直後の十六進文字を値へ含めるか本文とみなすかを固定幅や暗黙の慣行に頼る。実装の前提が違えば同じ入力が別の値になる。

RFC 5137 の一案は、小文字 backslash-u に続けてアポストロフィで四〜六桁を囲む。もう一案は XML の十六進数値文字参照で、末尾セミコロンを維持する。HTML 風にセミコロンを省けば、境界を明示する利点が消える。導入文字自身の表現方法も仕様に必要だ。

重要なのは句読点の統一ではない。関連プロトコルとの一貫性を優先する場合もある。必要なのは、導入、桁数、大文字小文字、終端、許容範囲、リテラル表現、エラー時動作を一つの構文として閉じることである。

試験では、四・五・六桁の境界、直後の十六進文字、欠けた終端、サロゲート範囲、上限超過、導入文字、途中切断を扱う。単一ライブラリで生成と解析を往復しても、同じ思い込みを二度使うだけかもしれない。異なる実装間の一致が相互運用の証拠になる。

見慣れた \u が契約を隠す

\u は普遍的な Unicode 記号に見える。しかし C は小文字と大文字で桁数を変え、Java は四桁を UTF-16 コード単位として扱う。JSON も四桁形式を持ち、補助文字には二つを使う。波括弧や可変長を採用する環境もある。

個々の文脈では正しい規則である。問題は、表記だけを別の境界へ持ち出すことだ。送信側がコード単位、受信側がコードポイントだと思っても、BMP 内のテストでは差が出ない。補助平面を含む実データで初めて破綻する。

JSON では RFC 8259 が固有の文字列文法を定義する。I-JSON は有効な Unicode スカラー値を求め、対応しないサロゲートの不安定さを抑える。強い相互運用性は、\u の見た目ではなく、追加プロファイルの明示から生まれる。

移行時の自動判定も危険だ。旧式のオクテット形式と新しいコードポイント形式は、復号前にバージョンや構文で識別できるべきである。どの生産者がどの契約を使うかを計測しなければ、寛容な互換経路は永久に残り、厳格化できない。

正規化はアンエスケープの後にある

Unicode では異なるコードポイント列が正準等価になることがある。UAX #15 は NFC、NFD、NFKC、NFKD を定義する。RFC 5198 は Net-Unicode に UTF-8 と NFC を選び、W3C の文字モデルは仕様に受理形・生成形・照合方法を明記するよう求める。

これらは RFC 5137 の仕事ではない。明確なエスケープから正確な列を得ても、別表現との等価性は残る。フィールドのプロファイルが禁止する文字も復元できる。構文、スカラー妥当性、正規化、用途適合性は連続する別の検査である。

順番を誤ると制御が抜ける。ASCII 表記だけを禁止語検査した後でアンエスケープすれば、数値表記が禁止文字を生成できる。一意性を正規化前、検索を NFC 後に行えば、登録時は別だった二件が同じキーへ収束する。表示時だけ正規化すれば、人には同じでも権限上は別という逆の問題が起きる。

したがって、エスケープ文法検証、スカラー復元、不正値拒否、指定正規化、文字列プロファイル、比較キー生成、認可という順序を公開する。正規化の受領書には形式、Unicode バージョン、入力、出力、実行箇所が必要だ。「正規化済み」という一語では足りない。

識別子は用途ごとの規則でできている

PRECIS は国際化識別子と自由形式文字列にクラスとプロファイルを提供し、文脈規則、正規化、比較を扱う。IDNA は DNS ラベルについて許容分類、NFC、A-label と U-label の関係を定める。いずれもコードポイント復元後の政策である。

Unicode として正しい値でも、ある識別子では禁止され得る。隣接文字、スクリプト、割当状態、バージョンに依存することもある。ドメイン名なら往復検証も関わる。数値エスケープは、登録可能性、所有権、到達先を証明しない。

視覚的な混同はさらに別だ。異なるコードポイントが似たグリフを持ち、同じ列でもフォント、シェーピング、双方向文脈で見え方が変わる。コードポイント表示は調査者の識別に役立つが、利用者の誤認を自動的に防がない。

高権限の識別子には、レパートリ制限、スクリプト方針、confusable 審査、衝突検知、表示名に依存しない復旧が必要になる。認可は不透明で安定した内部 ID に結び、国際化名は表示属性として管理する方が、見た目の曖昧さを権限選択から切り離せる。

変換ごとに証拠を置く

入口ではバイト列、符号化宣言、経路を記録する。パーサでは元の ASCII 表記、選択文法、拒否理由を記録する。Unicode 層ではスカラー列、プロファイル層では正規化、バージョン、文脈判定、比較キーを記録する。認可層では内部主体、資源、政策、結果を記録する。

人の判断に表示が関わるなら、フォント、シェーピング、ロケール、方向、周辺文字も必要だ。スクリーンショットは見え方を残すが格納列を証明しない。生ログは値を残すが、担当者が見た順序を証明しない。双方を関連付けて保存する。

端から端の試験は、実際の Java、JSON、UTF-8 サービス、データベース、クライアントを横断させる。補助平面、結合列、右から左の文字、リテラル導入文字、不正値を含める。置換文字を黙って挿入する実装は、成功ではなく識別子変更として計上する。

受領書の連鎖は障害時の責任を狭くする。Unicode 全体を漠然と疑う代わりに、どの変換で対象が変わったかを示せる。分かりやすい一画面が、観測していない現実まで支配することも防げる。

薄い標準の外側に権限を置く

RFC 5137 は小さな共通層を提供する。ASCII 境界が必要ならコードポイントを直接指し、終端を明確にする。文字列の有効性、登録、表示、認可を自分の権限へ取り込まないから、多様なプロトコルで利用できる。

組織も同じ分担を持つべきだ。プロトコル担当は構文、ランタイム担当はスカラー復号、国際化担当は正規化とプロファイル、製品担当は等価性と衝突、セキュリティ担当は処理順序と視覚混同、認可担当は内部主体との結合を所有する。

二次的な危険は、最も見やすい証拠を持つチームが、証拠の外まで判断することだ。正しい十六進数を見てアカウントまで正しいと結論し、期待した字形を見て保存値まで同じと結論する。局所的に正しい表示が、境界を失って全体の誤認へ変わる。

RFC 5137 は最初の一枚を良くする規格である。最後の一枚にしてはいけない。

出典

  1. RFC 5137 HTML
  2. RFC 5137 プレーンテキスト
  3. RFC Editor の RFC 5137 情報
  4. IETF Datatracker の RFC 5137
  5. RFC 5137 文書履歴
  6. RFC 5137 正誤表検索
  7. RFC 3629:UTF-8
  8. RFC 2781:UTF-16
  9. RFC 5198:Net-Unicode
  10. RFC 6365:国際化用語
  11. RFC 2277:IETF の言語と文字集合方針
  12. RFC 8259:JSON
  13. RFC 7493:I-JSON
  14. RFC 8264:PRECIS フレームワーク
  15. RFC 5890:IDNA 定義
  16. RFC 5891:IDNA プロトコル
  17. Unicode 標準附属書第15号
  18. W3C 文字モデル
  19. 最小初期仕様、局所化された将来判断、自発的採用
  20. 現実の層、象徴権力、そして明瞭さが敵対的に見える理由
  21. Running-Code Primary