Skip to content

--subnet accepts an out-of-range prefix length without validation #86

Description

@toshi0806

現象

--subnet の prefix 長が検証されていない。負の値がそのまま EDNS Client Subnet オプションの source_prefix になる。

$ # Tdig.CLI.parse_subnet_option/1 の実測
192.0.2.1/24:   source_prefix: 24
192.0.2.1/-5:   source_prefix: -5     ← 負値がそのまま通る
192.0.2.1/999:  source_prefix: 32     ← 上限だけは効く
2001:db8::1/-1: source_prefix: -1

原因

lib/tdig/cli.exparse_subnet_option/1

prefix = String.to_integer(prefix_str)
...
source_bits = min(prefix, 32)   # IPv6 側は min(prefix, 128)

としており、min/2上限しか抑えない。下限のチェックが無く、String.to_integer/1"-5" を素直に -5 にする。

RFC 7871 の SOURCE PREFIX-LENGTH は 8 bit の符号なし整数なので、負値は表現できない。

影響

パケット組み立て側の扱い次第だが、いずれにせよ利用者の意図しないクエリが送られる。dig+subnet=192.0.2.1/-5invalid prefix length で拒否する。

検討事項

挙動の変更を伴うため、方針を決める必要がある。

  1. 範囲外をエラーにするdig に合わせる。既存の Invalid subnet format と同じく stderr + System.halt(1)
  2. 0 にクランプする

dig 互換を掲げているので 1 が素直だと考える。

あわせて String.to_integer/1"abc"ArgumentError を投げるため、--subnet 192.0.2.1/abc がスタックトレースを出す点も同時に見るとよい。

経緯

PR #85(Dialyzer の contract_supertype 解消)のレビューで source_prefixnon_neg_integer() にできないかという指摘があり、実測したところ実装が負値を返し得ることが分かった。spec は実装に忠実な integer() に据え置き、入力検証の欠落は挙動変更を伴うため本 issue に分離した。

https://claude.ai/code/session_01YAjSJR67tWTvYDJLcQThbQ

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions