}
-DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed)
+DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, uint16_t minOffset)
{
if (offset >= len)
throw std::range_error("Trying to read past the end of the buffer ("+std::to_string(offset)+ " >= "+std::to_string(len)+")");
}
}
- packetParser(pos, len, offset, uncompress, qtype, qclass, consumed);
+ packetParser(pos, len, offset, uncompress, qtype, qclass, consumed, 0, minOffset);
}
// this should be the __only__ dns name parser in PowerDNS.
-void DNSName::packetParser(const char* qpos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, int depth)
+void DNSName::packetParser(const char* qpos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, int depth, uint16_t minOffset)
{
const unsigned char* pos=(const unsigned char*)qpos;
unsigned char labellen;
if (offset >= len)
throw std::range_error("Trying to read past the end of the buffer ("+std::to_string(offset)+ " >= "+std::to_string(len)+")");
+ if (offset < (int) minOffset)
+ throw std::range_error("Trying to read before the beginning of the buffer ("+std::to_string(offset)+ " < "+std::to_string(minOffset)+")");
const unsigned char* end = pos + len;
pos += offset;
int newpos = (labellen << 8) + *(const unsigned char*)pos;
if(newpos < offset) {
+ if(newpos < (int) minOffset)
+ throw std::range_error("Invalid label position during decompression ("+std::to_string(newpos)+ " < "+std::to_string(minOffset)+")");
if (++depth > 100)
throw std::range_error("Abort label decompression after 100 redirects");
- packetParser((const char*)opos, len, newpos, true, 0, 0, 0, depth);
+ packetParser((const char*)opos, len, newpos, true, 0, 0, 0, depth, minOffset);
} else
throw std::range_error("Found a forward reference during label decompression");
pos++;
DNSName() {} //!< Constructs an *empty* DNSName, NOT the root!
explicit DNSName(const char* p); //!< Constructs from a human formatted, escaped presentation
explicit DNSName(const std::string& str) : DNSName(str.c_str()) {}; //!< Constructs from a human formatted, escaped presentation
- DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0); //!< Construct from a DNS Packet, taking the first question if offset=12
+ DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0, uint16_t minOffset=0); //!< Construct from a DNS Packet, taking the first question if offset=12
bool isPartOf(const DNSName& rhs) const; //!< Are we part of the rhs name?
bool operator==(const DNSName& rhs) const; //!< DNS-native comparison (case insensitive) - empty compares to empty
private:
string_t d_storage;
- void packetParser(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0, int depth=0);
+ void packetParser(const char* p, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed, int depth, uint16_t minOffset);
static std::string escapeLabel(const std::string& orig);
static std::string unescapeLabel(const std::string& orig);
};
{
unsigned int consumed;
try {
- DNSName dn((const char*) d_content.data() - 12, d_content.size() + 12, d_pos + sizeof(dnsheader), true /* uncompress */, 0 /* qtype */, 0 /* qclass */, &consumed);
+ DNSName dn((const char*) d_content.data() - 12, d_content.size() + 12, d_pos + sizeof(dnsheader), true /* uncompress */, 0 /* qtype */, 0 /* qclass */, &consumed, sizeof(dnsheader));
// the -12 fakery is because we don't have the header in 'd_content', but we do need to get
// the internal offsets to work