{
const auto* data = str.data();
uint16_t len;
+ if (str.size() < sizeof(len)) {
+ return 0;
+ }
memcpy(&len, data, sizeof(len));
if (str.size() < serialize_prefix_size + len + serialize_trailing_size) {
return 0;
}
// Deserialize a single resource record.
-static void deserializeFromBuffer(const string_view& buffer, LMDBBackend::LMDBResourceRecord& value)
+// Returns true if successful, false if truncated or invalid data found.
+static bool deserializeFromBuffer(const string_view& buffer, LMDBBackend::LMDBResourceRecord& value)
{
- if (buffer.size() >= serialize_minimum_size) {
- deserializeRRFromBuffer(buffer, value);
- }
+ return deserializeRRFromBuffer(buffer, value) != 0;
}
// Deserialize a list of resource records.
// }
static bool peekAtHasOrderName(const string_view& buffer)
{
+ if (buffer.length() < sizeof(uint16_t)) {
+ return false;
+ }
uint16_t len{0};
memcpy(&len, buffer.data(), sizeof(uint16_t));
- bool hasOrderName = buffer[serialize_prefix_size + len + serialize_offset_ordername] != 0;
+ auto offset = serialize_prefix_size + len + serialize_offset_ordername;
+ if (buffer.length() < offset + 1) {
+ return false;
+ }
+ bool hasOrderName = buffer[offset] != 0;
return hasOrderName;
}
// Similar to the above, but for the auth field.
static bool peekAtAuth(const string_view& buffer)
{
+ if (buffer.length() < sizeof(uint16_t)) {
+ return false;
+ }
uint16_t len{0};
memcpy(&len, buffer.data(), sizeof(uint16_t));
- bool auth = buffer[serialize_prefix_size + len + serialize_offset_auth] != 0;
+ auto offset = serialize_prefix_size + len + serialize_offset_auth;
+ if (buffer.length() < offset + 1) {
+ return false;
+ }
+ bool auth = buffer[offset] != 0;
return auth;
}
// Similar to the above, but for the ttl.
static uint32_t peekAtTtl(const string_view& buffer)
{
+ if (buffer.length() < sizeof(uint16_t)) {
+ return 0;
+ }
uint16_t len{0};
memcpy(&len, buffer.data(), sizeof(uint16_t));
+ auto offset = serialize_prefix_size + len + serialize_offset_ttl;
+ if (buffer.length() < offset + sizeof(uint32_t)) {
+ return 0;
+ }
uint32_t ttl{0};
- memcpy(&ttl, buffer.data() + serialize_prefix_size + len + serialize_offset_ttl, sizeof(uint32_t));
+ memcpy(&ttl, buffer.data() + offset, sizeof(uint32_t));
return ttl;
}
auto key = co(domain_id, qname, QType::NSEC3);
if (txn->txn->get(txn->db->dbi, key, val) == 0) {
LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<string_view>(), lrr);
- DNSName ordername(lrr.content.c_str(), lrr.content.size(), 0, false);
- txn->txn->del(txn->db->dbi, co(domain_id, ordername, QType::NSEC3));
+ if (deserializeFromBuffer(val.get<string_view>(), lrr)) {
+ DNSName ordername(lrr.content.c_str(), lrr.content.size(), 0, false);
+ txn->txn->del(txn->db->dbi, co(domain_id, ordername, QType::NSEC3));
+ }
txn->txn->del(txn->db->dbi, key);
}
}
MDBOutVal val{};
if (txn->txn->get(txn->db->dbi, co(domain_id, qname, QType::NSEC3), val) == 0) {
LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<string_view>(), lrr);
- DNSName prevordername(lrr.content.c_str(), lrr.content.size(), 0, false);
- if (prevordername == ordername) {
- return; // nothing to do! (assuming the other record also exists)
+ if (deserializeFromBuffer(val.get<string_view>(), lrr)) {
+ DNSName prevordername(lrr.content.c_str(), lrr.content.size(), 0, false);
+ if (prevordername == ordername) {
+ return; // nothing to do! (assuming the other record also exists)
+ }
+ txn->txn->del(txn->db->dbi, co(domain_id, prevordername, QType::NSEC3));
}
- txn->txn->del(txn->db->dbi, co(domain_id, prevordername, QType::NSEC3));
}
LMDBResourceRecord lrr;
}
deserializeMultipleFromBuffer(d_lookupstate.val.get<string_view>(), d_lookupstate.rrset);
- d_lookupstate.rrsettime = static_cast<time_t>(LMDBLS::LSgetTimestamp(d_lookupstate.val.getNoStripHeader<string_view>()) / (1000UL * 1000UL * 1000UL));
- d_lookupstate.rrsetpos = 0;
+ if (!d_lookupstate.rrset.empty()) {
+ d_lookupstate.rrsettime = static_cast<time_t>(LMDBLS::LSgetTimestamp(d_lookupstate.val.getNoStripHeader<string_view>()) / (1000UL * 1000UL * 1000UL));
+ d_lookupstate.rrsetpos = 0;
+ }
}
else {
key = d_lookupstate.key.getNoStripHeader<string_view>();
MDBOutVal val;
if (!txn->txn->get(txn->db->dbi, co(di.id, g_rootdnsname, QType::SOA), val)) {
LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<string_view>(), lrr);
- if (lrr.content.size() >= sizeof(soatimes)) {
- soatimes st;
- // A SOA has five 32 bit fields, the first of which is the serial;
- // there are two variable length names before the serial, so we calculate from the back.
- memcpy(&st.serial, &lrr.content[lrr.content.size() - sizeof(soatimes)], sizeof(st.serial));
- di.serial = ntohl(st.serial);
+ if (deserializeFromBuffer(val.get<string_view>(), lrr)) {
+ if (lrr.content.size() >= sizeof(soatimes)) {
+ soatimes st;
+ // A SOA has five 32 bit fields, the first of which is the serial;
+ // there are two variable length names before the serial, so we calculate from the back.
+ memcpy(&st.serial, &lrr.content[lrr.content.size() - sizeof(soatimes)], sizeof(st.serial));
+ di.serial = ntohl(st.serial);
+ }
+ return !lrr.disabled;
}
- return !lrr.disabled;
}
return false;
}
MDBOutVal val;
if (!txn2->txn->get(txn2->db->dbi, co(di.id, g_rootdnsname, QType::SOA), val)) {
LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<string_view>(), lrr);
- soatimes st;
- // There are two variable length names before the SOA numbers, so we calculate from the back.
- memcpy(&st, &lrr.content[lrr.content.size() - sizeof(soatimes)], sizeof(soatimes));
- if ((time_t)(di.last_check + ntohl(st.refresh)) > now) { // still fresh
- return false;
+ if (deserializeFromBuffer(val.get<string_view>(), lrr)) {
+ if (lrr.content.size() >= sizeof(soatimes)) {
+ soatimes st;
+ // There are two variable length names before the SOA numbers, so we calculate from the back.
+ memcpy(&st, &lrr.content[lrr.content.size() - sizeof(soatimes)], sizeof(soatimes));
+ if ((time_t)(di.last_check + ntohl(st.refresh)) > now) { // still fresh
+ return false;
+ }
+ }
}
}
-
return true;
});
}
before = co.getQName(key.getNoStripHeader<StringView>());
{
LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<StringView>(), lrr);
- unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + info.zone.operator const DNSName&();
+ if (deserializeFromBuffer(val.get<StringView>(), lrr)) {
+ unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + info.zone.operator const DNSName&();
+ }
}
// now to find after .. at the beginning of the zone
return getAfterForwardFromStart(cursor, key, val, id, after);
before = co.getQName(key.getNoStripHeader<StringView>());
{
LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<StringView>(), lrr);
- unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + info.zone.operator const DNSName&();
+ if (deserializeFromBuffer(val.get<StringView>(), lrr)) {
+ unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + info.zone.operator const DNSName&();
+ }
}
// cout <<"Should still find 'after'!"<<endl;
// for 'after', we need to find the first hash of this zone
before = co.getQName(key.getNoStripHeader<StringView>());
{
LMDBResourceRecord lrr;
- deserializeFromBuffer(val.get<StringView>(), lrr);
- unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + info.zone.operator const DNSName&();
+ if (deserializeFromBuffer(val.get<StringView>(), lrr)) {
+ unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + info.zone.operator const DNSName&();
+ }
}
// cout<<"Went backwards, found "<<before<<endl;
// return us to starting point
MDBOutVal val{};
if (d_rotxn->txn->get(d_rotxn->db->dbi, order(info.id, basename, QType::NSEC3), val) == 0) {
LMDBResourceRecord nsec3rr;
- deserializeFromBuffer(val.get<string_view>(), nsec3rr);
- DNSName ordername(nsec3rr.content.c_str(), nsec3rr.content.size(), 0, false);
- ret << ordername;
+ if (deserializeFromBuffer(val.get<string_view>(), nsec3rr)) {
+ DNSName ordername(nsec3rr.content.c_str(), nsec3rr.content.size(), 0, false);
+ ret << ordername;
+ }
+ else {
+ ret << "TRUNCATED";
+ }
}
ret << "'\t";
ret << static_cast<int>(lrr.auth);