summaryrefslogtreecommitdiff
path: root/util/data/dname.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/data/dname.c')
-rw-r--r--util/data/dname.c58
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)
{