Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@monoidic
Copy link
Contributor

@monoidic monoidic commented Jul 4, 2025

At the moment, the code for unpacking RRs (mostly in the autogenerated code) is peppered with chunks of off == len(msg) checks which return with a nil error.
As far as I understand, this is a workaround for parsing messages with an rdlength of zero. This mostly works due to the noRdata check in UnpackRRWithHeader.
Removing these checks reveals that TestNoRdataUnpack does not actually produce zero-rdlength messages for a good number of rrtypes, so the noRdata early return does not trigger. These off == len(msg) clauses peppered everywhere cause parsing to instead succeed at the boundaries of arbitrary elements of a resource record, with the zero values assigned to the rest of the messages.
This means that malformed RRs which are too short, but happen to end at the right byte boundary, will be considered valid, with any remaining fields being kept as the zero value.
In fact, even a nil buffer would be parsed as a "valid" RR by dns.UnpackRR(nil, 0), producing this RR:

	0	CLASS0	TYPE0	\# 0 

This PR removes all of these checks while keeping functionality for real zero-rdlength RRs.
The malformed messages described above will no longer be considered valid.
TestNoRdataUnpack has been updated to manually adjust the RRs to produce actual zero-rdlength messages.

@monoidic monoidic requested review from miekg and tmthrgd as code owners July 4, 2025 07:24
@miekg
Copy link
Owner

miekg commented Jul 9, 2025

ohh, this is nice, and removes a whole bunch of (generated) code. IIRC this was added because of actual things going awry when parsing binary from the wire - but I dont thing we have a test for this :-(

To put it another way if you can show me a binary unpack test that would hit this if and it would still work with your PR it will certainly be merged. Might be fiddly to actually make that sort of packet though...

@monoidic
Copy link
Contributor Author

monoidic commented Jul 9, 2025

I'm not quite sure what you mean. Removing the ifs and making truncated messages (ones that would have hit them) invalid is the intentional here. Or do you mean some other if?

I have already provided (as of the second commit in this PR) an example test with an MX record where the rrdata section has been truncated to just 2 bytes, which covers just the preference uint16 and has no space for the following MX name field. Previously, this would have hit the if off == len(msg) and have been considered valid. Currently, it is treated as invalid due to there not being enough space for the following fields.
Perhaps a different RR type with more than 2 fields would have been a better example.
None the less, I'd like to point out that had the rrdata been truncated to 1 byte instead, it would have errored out before as well, due to unpackUint16 refusing to unpack a single byte into a uint16.

Is there some reason why splicing arbitrary RRs at field bounds like that should be considered valid? Splicing at points besides those bounds was already invalid.
If there is some reason why this should be considered valid, then it should at least be made clear in some way.

@miekg
Copy link
Owner

miekg commented Aug 16, 2025

https://codeberg.org/miekg/dns used @tmthrgd cryptobyte.String which neatly solves this.

I'm not going to merge such an invasive PR here

@miekg miekg closed this Aug 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants