問題
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/2(lib/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層あり、両方に対応する:
- dig 互換の引数解釈:
parse_argv_item/2 で、位置引数が既知の RR type / class 名(case-insensitive)に一致する場合はその位置に関係なく type / class として解釈する(本家 dig と同じ挙動)。名前が type 名と衝突するケース(例: ホスト名 txt)は dig 同様 type 解釈を優先する。
- 不正 type のエラーハンドリング: 未知の type が指定された場合、パケット生成まで進んで stacktrace 付きでクラッシュするのではなく、CLI 層で
;; Unknown type: ... のようなメッセージを出して exit する。また str2atom/1 の String.to_atom/1 は任意入力から atom を生成するため、既知の type/class への membership 判定と組み合わせる。
TDD で、上記の再現ケース(type-first / 未知 type)をテストに起こしてから実装する。
問題
tdig txt sony.comのようにクエリタイプを名前より先に指定すると、DNS パケット生成時にArgumentErrorでクラッシュする。原因(裏取り済み)
Tdig.CLI.parse_argv_item/2(lib/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./tdig sony.com TXT./tdig txt sony.com./tdig TXT sony.comdig txt sony.com(BIND dig)本家 dig は位置引数のトークンが既知の type/class 名なら位置に関係なく type/class として解釈するため、
dig txt sony.comは動作する。dig 互換を謳う tdig との差異になっている。対応
問題は2層あり、両方に対応する:
parse_argv_item/2で、位置引数が既知の RR type / class 名(case-insensitive)に一致する場合はその位置に関係なく type / class として解釈する(本家 dig と同じ挙動)。名前が type 名と衝突するケース(例: ホスト名txt)は dig 同様 type 解釈を優先する。;; Unknown type: ...のようなメッセージを出して exit する。またstr2atom/1のString.to_atom/1は任意入力から atom を生成するため、既知の type/class への membership 判定と組み合わせる。TDD で、上記の再現ケース(type-first / 未知 type)をテストに起こしてから実装する。