bs_cache_path が namespace の長さを考慮してキャッシュサイズ上限を検証
bs_cache_path がキャッシュディレクトリと namespace の合計長を正しく検証できるようになり、長い名前空間でのパス生成エラーを防止します。
背景
bs_cache_path は cachedir、namespace、path からキャッシュファイルのフルパスを組み立てる中心的関数です。現在は MAX_CACHEDIR_SIZE(定義は #define MAX_CACHEDIR_SIZE 981)という上限があり、従来は cachedir の長さだけがチェック対象でした。
namespace が長い場合に合計が上限を超えても検証が行われず、内部バッファが予期せぬサイズになり例外やクラッシュが発生するリスクがありました。実際に長い名前空間を利用する環境でキャッシュパス生成が失敗する事例が報告されていました。
この問題を解消するために、PR #554 が作成され、namespace の長さも上限チェックに組み込む変更が提案されました。
技術的な変更
bs_cache_path 関数内で namespace の有無を判定し、長さを取得して上限計算に利用するロジックが追加されました。具体的には namespace_len 変数を 0 で初期化し、namespace_v が nil でなければ文字列長を代入します。
@@
Check_Type(cachedir_v, T_STRING);
Check_Type(path_v, T_STRING);
+ long namespace_len = 0;
if (!NIL_P(namespace_v)) {
Check_Type(namespace_v, T_STRING);
+ namespace_len = RSTRING_LEN(namespace_v);
}
-
- if (RSTRING_LEN(cachedir_v) > MAX_CACHEDIR_SIZE) {
+ if (RSTRING_LEN(cachedir_v) + namespace_len > MAX_CACHEDIR_SIZE) {
rb_raise(rb_eArgError, "cachedir too long");
}
上記変更により cachedir と namespace の合計長が MAX_CACHEDIR_SIZE を超えると rb_eArgError が送出され、従来と同じ例外型で安全に失敗を通知します。namespace が nil のときは namespace_len が 0 になるため、既存の動作と互換性が保たれます。
このロジックは数行の追加に留まり、パフォーマンスへの影響は無視できる程度です。上限チェックは関数冒頭で行われるため、以降の処理は常に安全な前提で進められます。
設計判断
サイズ上限チェックに namespace 長を組み込むことで、入力検証の一貫性が向上し、潜在的なバッファオーバーフローリスクが低減します。例外の種類やメッセージは変更せず、既存コードが期待するエラーハンドリングをそのまま利用できる点が設計上の利点です。
変更は namespace の有無を安全に判定し、長さを取得するだけの最小限のロジック追加です。そのため既存の API 署名や呼び出し側コードへの影響はなく、後方互換性が完全に維持されます。
この判断は「最小の変更で安全性を高める」方針に沿っており、将来的に MAX_CACHEDIR_SIZE が変更された場合でも同様の計算ロジックが適用できる拡張性を保持します。
まとめ
PR #554 の変更により、bs_cache_path は namespace の長さも考慮した上でキャッシュディレクトリサイズ上限を検証します。これにより長い名前空間でも安全にキャッシュパスが生成でき、既存のエラーハンドリングと互換性を保ったまま重要な安全性向上が実現されました。