After decoding a name, resolv_read_name() computes the number of bytes
the name occupies in the message by scanning it byte by byte until it
finds either a zero byte or a byte with the two upper bits set, which it
takes for the terminating zero or a compression pointer. But labels may
contain any byte, so a label containing a zero byte or a byte >= 0xc0
stops the scan in the middle of the name, and the rest of the message is
parsed from this wrong position, generally resulting in the response
being considered invalid.
Such bytes are found for example in names using raw UTF-8 characters
instead of their IDNA form, which do-resolve may be asked to resolve:
"caf\xc3\xa9.test" is correctly sent in the query, but the valid response
is rejected because the question name is believed to end at 0xc3 (seen
as a pointer), and do-resolve fails while plain names work.
Let's walk the labels instead, as the first loop already validated them.
This patch may be backported to stable branches.
out:
/* offset computation:
- * parse from <name> until finding either NULL or a pointer "c0xx"
+ * walk the labels from <name> until finding either the terminating
+ * zero or a pointer "c0xx". Labels may contain any byte, and were
+ * already validated above.
*/
reader = name;
*offset = 0;
*offset += 1;
break;
}
- *offset += 1;
- ++reader;
+ *offset += *reader + 1;
+ reader += *reader + 1;
}
return nb_bytes;