diff options
Diffstat (limited to 'src/shared/dns-domain.c')
-rw-r--r-- | src/shared/dns-domain.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index ba6eff8f60..03c0107308 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -864,7 +864,7 @@ bool dns_name_is_single_label(const char *name) { return dns_name_is_root(name); } -/* Encode a domain name according to RFC 1035 Section 3.1 */ +/* Encode a domain name according to RFC 1035 Section 3.1, without compression */ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) { uint8_t *label_length, *out; int r; @@ -875,24 +875,35 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) { out = buffer; do { - /* reserve a byte for label length */ + /* Reserve a byte for label length */ if (len <= 0) return -ENOBUFS; len--; label_length = out; out++; - /* convert and copy a single label */ + /* Convert and copy a single label. Note that + * dns_label_unescape() returns 0 when it hits the end + * of the domain name, which we rely on here to encode + * the trailing NUL byte. */ r = dns_label_unescape(&domain, (char *) out, len); if (r < 0) return r; - /* fill label length, move forward */ + /* Fill label length, move forward */ *label_length = r; out += r; len -= r; + } while (r != 0); + /* Verify the maximum size of the encoded name. The trailing + * dot + NUL byte account are included this time, hence + * compare against DNS_HOSTNAME_MAX + 2 (which is 255) this + * time. */ + if (out - buffer > DNS_HOSTNAME_MAX + 2) + return -EINVAL; + return out - buffer; } |