Fix DNSRRTSIG length fields not auto-computing#5045
Open
chuenchen309 wants to merge 1 commit into
Open
Conversation
DNSRRTSIG declared its two FieldLenField length prefixes with hardcoded defaults -- mac_len=20 and other_len=0 -- instead of None. FieldLenField only derives the length from its length_of target when the value is None, so the prefixes were frozen and never matched the actual mac_data / other_data. Consequences on the build/dissect round-trip: - Even the zero-argument DNSRRTSIG() cannot re-parse its own bytes: mac_len is 20 but mac_data is empty, so on dissect the mac_data StrLenField consumes the 20 bytes belonging to the trailing fields and the next getfield unpacks past the buffer (struct.error). - A real MAC (e.g. a 32-byte HMAC-SHA256) is silently truncated to 20 bytes on the wire, because the length prefix stays 20. Every other FieldLenField in dns.py -- DNSRROPT.rdlen, DNSRRNAPTR's flags_len/services_len/regexp_len, and the header counts -- uses None. Change mac_len and other_len to None so they auto-compute like their siblings. Two existing dns_dnssec.uts assertions had baked in the buggy 0x14 (mac_len=20 with an empty MAC); corrected to 0x00 and added a round-trip case that a 32-byte MAC and 6-byte other_data survive build->dissect. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> AI-Assisted: yes (Claude Opus 4.8)
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes DNSRRTSIG TSIG length-prefix fields (mac_len, other_len) so they auto-compute from their corresponding payload fields during build, restoring correct build→dissect round-tripping and preventing silent MAC truncation / mis-dissection.
Changes:
- Set
DNSRRTSIG.mac_lenandDNSRRTSIG.other_lenFieldLenFielddefaults toNoneso lengths are computed frommac_data/other_data. - Update existing TSIG raw-byte expectations that previously baked in the buggy hardcoded
mac_len=20. - Add a regression test covering non-empty
mac_data+other_dataround-trip with auto-computed lengths.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
scapy/layers/dns.py |
Fixes TSIG length fields to auto-compute instead of using hardcoded defaults. |
test/scapy/layers/dns_dnssec.uts |
Updates expectations for the corrected encoding and adds a regression round-trip assertion. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
guedou
approved these changes
Jul 18, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #5045 +/- ##
==========================================
+ Coverage 80.13% 80.21% +0.07%
==========================================
Files 388 388
Lines 96467 96467
==========================================
+ Hits 77308 77382 +74
+ Misses 19159 19085 -74
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
DNSRRTSIGdeclares its twoFieldLenFieldlength prefixes with hardcoded defaults —mac_len=20andother_len=0— instead ofNone.FieldLenFieldonly auto-computes the length from itslength_oftarget when the value isNone, so these prefixes were frozen and never matched the realmac_data/other_data, breaking the build/dissect round-trip.Even the zero-argument default can't re-parse its own bytes:
mac_lenis 20 butmac_datais empty, so on dissect themac_dataStrLenFieldconsumes the 20 bytes belonging to the trailing fields, and the nextgetfieldunpacks past the buffer. With a real MAC (e.g. a 32-byte HMAC-SHA256), the length prefix stays 20 and 12 bytes of the MAC are silently truncated on the wire.Every other
FieldLenFieldindns.py—DNSRROPT.rdlen,DNSRRNAPTR'sflags_len/services_len/regexp_len, and the header counts — usesNone.DNSRROPT(rdata=...)round-trips correctly for exactly that reason, which confirmsNoneis the intended pattern and the literal20/0are the defect.Fix: set
mac_lenandother_lendefaults toNoneso they auto-compute like their siblings (2 lines).Tests
Two existing
dns_dnssec.utsassertions had baked in the buggy\x14(mac_len=20 with an empty MAC); corrected to\x00, and added a round-trip case asserting a 32-byte MAC + 6-byteother_datasurvive build→dissect (mac_len/other_lenauto-compute to 32/6). The new case is red before the fix and green after.dns.uts(31) anddns_dnssec.utspass;flake8clean andmypyunchanged vs baseline.AI assistance: prepared with Claude Code (Claude Opus 4.8) — disclosed via the
AI-Assisted: yes (Claude Opus 4.8)commit trailer. I reproduced the crash, verified the round-trip fix against the siblingFieldLenFields, corrected the bug-baked test expectations, and reviewed every line before opening.