diff options
Diffstat (limited to 'util/data/dname.c')
-rw-r--r-- | util/data/dname.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/util/data/dname.c b/util/data/dname.c index 9f25e1efe204..76b2ec7d6d8a 100644 --- a/util/data/dname.c +++ b/util/data/dname.c @@ -233,17 +233,28 @@ int dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2) { uint8_t len1, len2; + int count1 = 0, count2 = 0; log_assert(pkt && d1 && d2); len1 = *d1++; len2 = *d2++; while( len1 != 0 || len2 != 0 ) { /* resolve ptrs */ if(LABEL_IS_PTR(len1)) { + if((size_t)PTR_OFFSET(len1, *d1) + >= sldns_buffer_limit(pkt)) + return -1; + if(count1++ > MAX_COMPRESS_PTRS) + return -1; d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); len1 = *d1++; continue; } if(LABEL_IS_PTR(len2)) { + if((size_t)PTR_OFFSET(len2, *d2) + >= sldns_buffer_limit(pkt)) + return 1; + if(count2++ > MAX_COMPRESS_PTRS) + return 1; d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2)); len2 = *d2++; continue; @@ -302,12 +313,18 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h) uint8_t labuf[LDNS_MAX_LABELLEN+1]; uint8_t lablen; int i; + int count = 0; /* preserve case of query, make hash label by label */ lablen = *dname++; while(lablen) { if(LABEL_IS_PTR(lablen)) { /* follow pointer */ + if((size_t)PTR_OFFSET(lablen, *dname) + >= sldns_buffer_limit(pkt)) + return h; + if(count++ > MAX_COMPRESS_PTRS) + return h; dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); lablen = *dname++; continue; @@ -341,6 +358,9 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname) return; } /* follow pointer */ + if((size_t)PTR_OFFSET(lablen, *dname) + >= sldns_buffer_limit(pkt)) + return; dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); lablen = *dname++; continue; @@ -369,6 +389,7 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname) void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname) { uint8_t lablen; + int count = 0; if(!out) out = stdout; if(!dname) return; @@ -382,6 +403,15 @@ void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname) fputs("??compressionptr??", out); return; } + if((size_t)PTR_OFFSET(lablen, *dname) + >= sldns_buffer_limit(pkt)) { + fputs("??compressionptr??", out); + return; + } + if(count++ > MAX_COMPRESS_PTRS) { + fputs("??compressionptr??", out); + return; + } dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); lablen = *dname++; continue; @@ -558,6 +588,34 @@ dname_lab_startswith(uint8_t* label, char* prefix, char** endptr) return 1; } +int +dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label) +{ + size_t len; + + /* 1 byte needed for the label length */ + if(dnamelen < 1) + return 0; + + len = *dname; + while(len <= dnamelen) { + if(!(*dname)) { + if(*dname == *label) + return 1; /* empty label match */ + /* termination label found, stop iterating */ + return 0; + } + if(*dname == *label && *label && + memlowercmp(dname+1, label+1, *dname) == 0) + return 1; + len += *dname; + dname += *dname; + dname++; + len++; + } + return 0; +} + int dname_buffer_write(sldns_buffer* pkt, uint8_t* dname) { |