diff --git a/src/seeder/dns.h b/src/seeder/dns.h --- a/src/seeder/dns.h +++ b/src/seeder/dns.h @@ -8,6 +8,11 @@ #include #include +static const int MAX_QUERY_NAME_LENGTH = 255; +// Max size of the null-terminated buffer parse_name() writes to. +static constexpr int MAX_QUERY_NAME_BUFFER_LENGTH = MAX_QUERY_NAME_LENGTH + 1; +static const size_t MAX_LABEL_LENGTH = 63; + struct addr_t { int v; union { @@ -30,8 +35,8 @@ }; // 0: ok -// -1: premature end of input, forward reference, component > 63 char, invalid -// character +// -1: premature end of input, forward reference, label > MAX_LABEL_LENGTH, +// invalid character // -2: insufficient space in output int parse_name(const uint8_t **inpos, const uint8_t *inend, const uint8_t *inbuf, char *buf, size_t bufsize); diff --git a/src/seeder/dns.cpp b/src/seeder/dns.cpp --- a/src/seeder/dns.cpp +++ b/src/seeder/dns.cpp @@ -74,16 +74,16 @@ return -1; } // read length of next component - int octet = *((*inpos)++); + unsigned int octet = *((*inpos)++); if (octet == 0) { buf[bufused] = 0; return 0; } // add dot in output if (!init) { - // The maximum size of a query name is 255. The buffer must have - // room for at least the '.' and a valid non-'.' character - if (bufused > 253) { + // The buffer must have room for at least the '.', a valid + // non-'.' character, and a null-terminating character. + if (bufused > MAX_QUERY_NAME_BUFFER_LENGTH - 3) { return -1; } if (bufused == bufsize - 1) { @@ -106,12 +106,12 @@ return parse_name(&newbuf, (*inpos) - 2, inbuf, buf + bufused, bufsize - bufused); } - if (octet > 63) { + if (octet > MAX_LABEL_LENGTH) { return -1; } // copy label while (octet) { - if (*inpos == inend || bufused > 254) { + if (*inpos == inend || bufused > MAX_QUERY_NAME_LENGTH - 1) { return -1; } if (bufused == bufsize - 1) { @@ -128,7 +128,7 @@ } // 0: k -// -1: component > 63 characters +// -1: label > MAX_LABEL_LENGTH characters // -2: insufficent space in output // -3: two subsequent dots static int write_name(uint8_t **outpos, const uint8_t *outend, const char *name, @@ -139,18 +139,19 @@ if (!dot) { fin = name + strlen(name); } - if (fin - name > 63) { + unsigned int labelLength = fin - name; + if (labelLength > MAX_LABEL_LENGTH) { return -1; } if (fin == name) { return -3; } - if (outend - *outpos < fin - name + 2) { + if (outend - *outpos < labelLength + 2) { return -2; } - *((*outpos)++) = fin - name; - memcpy(*outpos, name, fin - name); - *outpos += fin - name; + *((*outpos)++) = labelLength; + memcpy(*outpos, name, labelLength); + *outpos += labelLength; if (!dot) { break; } @@ -421,9 +422,10 @@ { const uint8_t *inpos = inbuf + 12; const uint8_t *inend = inbuf + insize; - char name[256]; + char name[MAX_QUERY_NAME_BUFFER_LENGTH]; int offset = inpos - inbuf; - int ret = parse_name(&inpos, inend, inbuf, name, 256); + int ret = parse_name(&inpos, inend, inbuf, name, + MAX_QUERY_NAME_BUFFER_LENGTH); if (ret == -1) { responseCode = DNSResponseCode::FORMAT_ERROR; goto error; diff --git a/src/seeder/test/dns_tests.cpp b/src/seeder/test/dns_tests.cpp --- a/src/seeder/test/dns_tests.cpp +++ b/src/seeder/test/dns_tests.cpp @@ -11,11 +11,7 @@ BOOST_AUTO_TEST_SUITE(dns_tests) -static const int MAX_QUERY_NAME_LENGTH = 255; -// Max size of the null-terminated buffer parse_name() writes to. -static const int MAX_QUERY_NAME_BUFFER_LENGTH = MAX_QUERY_NAME_LENGTH + 1; static const uint8_t END_OF_NAME_FIELD = 0; -static const size_t MAX_LABEL_LENGTH = 63; // Builds the name field of the question section of a DNS query static std::vector