Skip to content

Crash (ArgumentError) when query type is given before name (e.g. tdig txt sony.com) #77

Description

@toshi0806

問題

tdig txt sony.com のようにクエリタイプを名前より先に指定すると、DNS パケット生成時に ArgumentError でクラッシュする。

$ ./tdig txt sony.com
** (ArgumentError) construction of binary failed: segment 2 of type 'integer': expected an integer but got: nil
    (tenbin_dns 0.7.0) lib/dns_packet.ex:289: DNSpacket.create_question_item/1
    (elixir 1.19.5) lib/enum.ex:1688: Enum."-map/2-lists^map/1-1-"/2
    (tenbin_dns 0.7.0) lib/dns_packet.ex:278: DNSpacket.create_question/1
    (tenbin_dns 0.7.0) lib/dns_packet.ex:248: DNSpacket.create/1
    (tdig 0.3.0) lib/tdig.ex:54: Tdig.get_response/1
    (tdig 0.3.0) lib/tdig.ex:31: Tdig.resolve/1
    (elixir 1.19.5) lib/kernel/cli.ex:141: anonymous fn/3 in Kernel.CLI.exec_fun/2

原因(裏取り済み)

Tdig.CLI.parse_argv_item/2lib/tdig/cli.ex)が位置引数を順序固定(1個目 → name、2個目 → type、3個目 → class)で解釈しているため:

  • txt が name(txt.)として、sony.com が type として解釈される
  • str2atom("sony.com") が atom :"sony.com" を生成 → tenbin_dns の type コード変換が nil を返す → create_question_item/1 のバイナリ構築で nil を整数セグメントに埋め込もうとしてクラッシュ

再現確認

コマンド 結果
./tdig sony.com txt ✅ 正常(TXT 応答取得)
./tdig sony.com TXT ✅ 正常
./tdig txt sony.com ❌ ArgumentError
./tdig TXT sony.com ❌ ArgumentError
dig txt sony.com(BIND dig) ✅ 正常(TXT 応答取得)

本家 dig は位置引数のトークンが既知の type/class 名なら位置に関係なく type/class として解釈するため、dig txt sony.com は動作する。dig 互換を謳う tdig との差異になっている。

対応

問題は2層あり、両方に対応する:

  1. dig 互換の引数解釈: parse_argv_item/2 で、位置引数が既知の RR type / class 名(case-insensitive)に一致する場合はその位置に関係なく type / class として解釈する(本家 dig と同じ挙動)。名前が type 名と衝突するケース(例: ホスト名 txt)は dig 同様 type 解釈を優先する。
  2. 不正 type のエラーハンドリング: 未知の type が指定された場合、パケット生成まで進んで stacktrace 付きでクラッシュするのではなく、CLI 層で ;; Unknown type: ... のようなメッセージを出して exit する。また str2atom/1String.to_atom/1 は任意入力から atom を生成するため、既知の type/class への membership 判定と組み合わせる。

TDD で、上記の再現ケース(type-first / 未知 type)をテストに起こしてから実装する。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions