From: Bert Hubert Date: Mon, 27 Dec 2010 21:01:55 +0000 (+0000) Subject: interim commit to get it out of the way X-Git-Tag: auth-3.0~485 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f5c700f0672cfce2e06cce18dd8feead4b92dfb2;p=pdns interim commit to get it out of the way git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1762 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/dnslabel.cc b/pdns/dnslabel.cc index a3ef293d9..7c5259d21 100644 --- a/pdns/dnslabel.cc +++ b/pdns/dnslabel.cc @@ -114,6 +114,13 @@ int DNSLabel::validateConsume(const char* raw, unsigned int maxLen) if(p > (const unsigned char*)raw + maxLen) // beyond the end return -1; + cerr<<(int)*p<= 0xc0 && p + 1 < (const unsigned char*)raw + maxLen) { + unsigned int offset=(*p & ~0xc0) * 0xff + *(p+1); + ++p; + cerr<<"Wants to refer to offset "< 64) // label length too long, or a compression pointer return -1; @@ -143,7 +150,6 @@ string DNSLabel::human() const ++p; ret.append(p, (int)labelLen); - if(!labelLen) break; ret.append(1, '.'); @@ -174,9 +180,25 @@ string DNSLabel::binary() const return std::string(getStart(), getLength()); } -void DNSLabel::expandCapacity() +static unsigned int roundUpToNextPowerOfTwo(unsigned int x) { - d_capacity *= 2; + x--; + x |= x >> 1; // handle 2 bit numbers + x |= x >> 2; // handle 4 bit numbers + x |= x >> 4; // handle 8 bit numbers + x |= x >> 8; // handle 16 bit numbers + x |= x >> 16; // handle 32 bit numbers + x++; + + return x; +} +void DNSLabel::expandCapacity(unsigned int len) +{ + if(!len) + d_capacity *= 2; + else { + d_capacity = roundUpToNextPowerOfTwo(d_capacity + len); + } char *newStorage = new char[d_capacity]; memcpy(newStorage, d_storage, d_fulllen); delete[] d_storage; @@ -192,6 +214,58 @@ DNSLabel DNSLabel::createFromBuffer(const char* raw, unsigned int* len) return DNSLabel(raw, result); } +void DNSLabel::chaseLabel(const char* raw, const char* beginPacket, unsigned int packetLength, unsigned int* len, bool updateLen) +{ + const unsigned char* p = (const unsigned char*) raw; + + for(;;) { + if(p > (const unsigned char*)beginPacket + packetLength) // beyond the end + throw std::range_error("label begins beyond end of packet"); + + if(*p >= 0xc0 && p + 1 < (const unsigned char*)beginPacket + packetLength) { + unsigned int offset=(*p & ~0xc0) * 256 + *(p+1); + if(offset < 12) + throw std::range_error("compression pointer to before beginning of content"); + offset -= 12; + cerr<<"new offset: "<= p) { + throw std::runtime_error("looping or forward compression pointer"); + } + + p+=2; + if(updateLen) { + *len = (p - (const unsigned char*)raw); + } + + chaseLabel(beginPacket + offset, beginPacket, packetLength, len, false); + return; + } + if(*p > 64) // label length too long, or a compression pointer + throw std::range_error("label too long"); + + if(!*p) { // final label, setbytes consumed + appendChar(0); + if(updateLen) + *len = 1 + (p - (const unsigned char*)raw); + return; + } + appendChar(*p); + appendRange((const char*)p+1, *p); + p += *p + 1; + } + // we should not get here, but if we do, it's bad +} + +DNSLabel::DNSLabel(const char* raw, const char* beginPacket, unsigned int packetLength, unsigned int* len) +{ + init(); + if(!*len) { + throw std::range_error("void label"); // shortest ok label is: '\x00' + } + + chaseLabel(raw, beginPacket, packetLength, len, true); +} + #if 0 void endsOn(const DNSLabel& first, const DNSLabel& second) { diff --git a/pdns/dnslabel.hh b/pdns/dnslabel.hh index 06c73e196..7300f517e 100644 --- a/pdns/dnslabel.hh +++ b/pdns/dnslabel.hh @@ -51,6 +51,7 @@ class DNSLabel explicit DNSLabel(const std::string& human); DNSLabel(const char* raw, unsigned int length); DNSLabel(const DNSLabel& rhs); + DNSLabel(const char* raw, const char* beginPacket, unsigned int packetLength, unsigned int* len); DNSLabel(); ~DNSLabel(); string human() const; @@ -87,5 +88,14 @@ class DNSLabel expandCapacity(); d_storage[d_fulllen++]= c; } - void expandCapacity(); + void appendRange(const char* ptr, unsigned int len) + { + if(d_fulllen + len > d_capacity) + expandCapacity(len); + memcpy(d_storage + d_fulllen, ptr, len); + d_fulllen += len; + } + + void expandCapacity(unsigned int len=0); + void chaseLabel(const char* raw, const char* beginPacket, unsigned int packetLength, unsigned int* len, bool updateLen); };