Skip to content

Resolv: build DNS wire messages as binary strings - #163

Open
TheRealAlexxx wants to merge 1 commit into
ruby:masterfrom
TheRealAlexxx:bug-19697
Open

TheRealAlexxx wants to merge 1 commit into
ruby:masterfrom
TheRealAlexxx:bug-19697

Conversation

@TheRealAlexxx

Copy link
Copy Markdown

Resolv: build DNS wire messages as binary strings

Fixes [Bug #19697].

Resolv::DNS::MessageEncoder accumulates the encoded packet in a UTF-8 buffer. When a query name contains non-ASCII characters, such as an internationalized domain name, the buffer becomes a UTF-8 string holding non-ASCII bytes, and binary writes into it start failing: assigning the request id in ConnectedUDP#sender (request[0,2] = ...) raises Encoding::CompatibilityError (incompatible character encodings: UTF-8 and ASCII-8BIT), so resolving such a name crashes before any packet is sent. The same hazard exists mid-encode, where put_length16 backpatches a packed length into the buffer after writing a name.

The wire format is bytes, so keep the buffer binary throughout: start it as ASCII-8BIT and append the binary form of byte strings, labels and character-strings. (An empty buffer adopts the encoding of the first string appended to it, so the initial conversion alone is not enough.) Message#encode now consistently returns an ASCII-8BIT string, matching what the socket layer and Message.decode already work with.

The new test resolves an internationalized domain name against a stub DNS server; without the change it raises Encoding::CompatibilityError in ConnectedUDP#sender.

Fixes [Bug #19697].

`Resolv::DNS::MessageEncoder` accumulates the encoded packet in a UTF-8 buffer. When a query name contains non-ASCII characters, such as an internationalized domain name, the buffer becomes a UTF-8 string holding non-ASCII bytes, and binary writes into it start failing: assigning the request id in `ConnectedUDP#sender` (`request[0,2] = ...`) raises `Encoding::CompatibilityError` (incompatible character encodings: UTF-8 and ASCII-8BIT), so resolving such a name crashes before any packet is sent. The same hazard exists mid-encode, where `put_length16` backpatches a packed length into the buffer after writing a name.

The wire format is bytes, so keep the buffer binary throughout: start it as ASCII-8BIT and append the binary form of byte strings, labels and character-strings. (An empty buffer adopts the encoding of the first string appended to it, so the initial conversion alone is not enough.) `Message#encode` now consistently returns an ASCII-8BIT string, matching what the socket layer and `Message.decode` already work with.

The new test resolves an internationalized domain name against a stub DNS server; without the change it raises `Encoding::CompatibilityError` in `ConnectedUDP#sender`.

This branch has not been deployed

No deployments
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.

1 participant