要約

  • XDRは各機械のメモリ配置を共有せず、最上位バイトを先に置く4バイト単位の外部表現を共有した。
  • 可変長値は長さと本体を持ち、その後のゼロ埋めは境界を整えるが値の一部にはならない。
  • 宣言順と判別子が構造を決める一方、TCP上のレコード境界、認証、認可、アプリケーション上の意味は別の層に残った。

九つの文字の後に三つの空白が来る

RFC 4506の例では、9バイトのファイル名を表すために、まず4バイトの長さ、その後に9バイトの名前、さらに3個のゼロを置く。次のフィールドはその先から始まる。ゼロを含めても名前の長さは9である。

この埋め草は捨ててよい偶然ではない。ゼロでなければならない。機械ごとのメモリ残片を許せば、同じ値が異なるバイト列へ化け、比較やチェックサムの前提が崩れる。意味を持たない場所にも一意の形を与えることで、XDRは等しい値を等しい表現へ近づけた。

内部差異を消したのではない。境界の外へ持ち出してよい差異だけを厳しく限定したのである。

ネイティブ表現は境界で降ろされた

1987年のRFC 1014は、異なる計算機アーキテクチャ間でデータを記述し符号化する標準としてXDRを示した。Sun RPCとNFSも利用例に含まれる。Cに似た記述言語は型を簡潔に示すためのもので、プログラムでも、C構造体のメモリ像でもない。

符号付き整数は32ビットの2の補数で、上位バイトから並ぶ。配列は要素順、構造体は宣言順に続く。各機械は内部で好みの形式を維持できるが、外へ出すときには共通形へ変換し、受け取るときにはそこから自分の形へ戻す。

対象ごとにエンディアンを知らせる印はない。二つの順序を許せば、それを選ぶ上位プロトコルが要るからだ。一つに固定する負担は機械によって異なるものの、セッション外に保存されたデータも、過去の交渉なしに読める。

4バイト幅も絶対的な最適値ではない。小さな単位は符号量を抑える代わりに整列上の不利を増やし、大きな単位は多くの機械を整列させる代わりに全体を膨らませる。公開された妥協点が四だった。

長さは内容と次の位置を分けた

可変長opaqueは32ビットの符号なし長を置き、指定された数の任意バイトを続け、4バイト境界までゼロを補う。文字列も同じ計数形式を持つ。可変長配列は要素数を先に示してから各要素を並べる。

受信側は、長さがプロトコルの上限内か、残りが足りるか、次の項目がどこから始まるかを自分で検査できる。宣言された最大値を超える符号化は誤りである。上限が省略されていても、受信者が言語上の最大値までメモリを差し出す義務はない。ローカルな資源制限は残る。

計数文字列にはNULも入り得る。NUL終端のネイティブ文字列へ不用意に移せば、確保した長さと、比較や解放で見える長さがずれる。共通形式の正しさは、ローカル変換の安全性まで代行しない。

判別子が次の型を一つだけ選んだ

XDRは暗黙の型付けを使う。通常のフィールドごとに名前と万能の型タグを送るのではなく、両端が同じ宣言を知っている。したがって構造体の宣言順は契約であり、順序の変更は後続バイトの読み方を変える。

判別共用体では、整数、列挙または真偽の判別子を先に置き、その値が後続するarmを選ぶ。defaultがない宣言で未知の値が来れば、有効な符号化ではない。optional-dataはその縮図で、真なら要素、偽なら0バイトのvoidを選ぶ。何もないことも、空の中身から推測せず選択値で示す。

ただし判別子が持つのは型を選ぶ権限だけだ。送信者の本人性、遠隔操作の許可、内容の妥当性までは証明しない。

表現とレコードは別の契約だった

1995年のRFC 1832は、普及していた形式を標準化トラックへ置いた。2006年のRFC 4506はSTD 67となり、RFC 1832への技術的変更を行わなかったと明記した。追加された安全上の注意は、長さ制限、バッファ、埋め込みNUL、再帰の深さなど実装側の責任を可視化した。

RFC 5531では、ONC RPCメッセージをXDRで記述しながら、TCP用のレコード・マーキングを別に定義する。そのフラグメントヘッダーはXDR標準形式ではないと明記される。つまりXDR値を一つ読めても、任意のTCPストリームにおけるメッセージ終端、対応する呼び出し、処理の確定までは分からない。

暗号化、認証、認可、リプレイ防止もXDRの仕事ではない。文法上の検査可能性と、相手を信頼してよい理由は別物である。

出典と限界

閉じた資料集合はRFC 1014、RFC 1832、RFC 4506、RFC 5531である。規則、改訂の連続性、RPCとの層境界は確認できるが、現在の採用率、製品の適合、実パケット、権限や実行結果は証明しない。