Commit aa9f341b authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2440] make sure old rdata don't contain duplicate; add doc and tests on this.

parent 0c87e932
......@@ -505,7 +505,9 @@ RdataEncoder::start(RRClass rrclass, RRType rrtype, const void* old_data,
// keep them in rdatas_ and rrsigs_ so we can detect and ignore duplicate
// data with the existing one later. We'll also figure out the lengths
// of the RDATA and RRSIG part of the data by iterating over the data
// fields.
// fields. Note that the given old_data shouldn't contain duplicate
// Rdata or RRSIG as they should have been generated by this own class,
// which ensures that condition; if this assumption doesn't hold, we throw.
size_t total_len = 0;
RdataReader reader(rrclass, rrtype, old_data, old_rdata_count,
old_sig_count,
......@@ -516,8 +518,11 @@ RdataEncoder::start(RRClass rrclass, RRType rrtype, const void* old_data,
while (reader.iterateRdata()) {
util::InputBuffer ibuffer(impl_->olddata_buffer_.getData(),
impl_->olddata_buffer_.getLength());
impl_->rdatas_.insert(createRdata(rrtype, rrclass, ibuffer,
impl_->olddata_buffer_.getLength()));
if (!impl_->rdatas_.insert(
createRdata(rrtype, rrclass, ibuffer,
impl_->olddata_buffer_.getLength())).second) {
isc_throw(Unexpected, "duplicate RDATA found in merging RdataSet");
}
impl_->olddata_buffer_.clear();
}
impl_->old_data_len_ = total_len;
......@@ -526,8 +531,11 @@ RdataEncoder::start(RRClass rrclass, RRType rrtype, const void* old_data,
while (reader.iterateSingleSig()) {
util::InputBuffer ibuffer(impl_->olddata_buffer_.getData(),
impl_->olddata_buffer_.getLength());
impl_->rrsigs_.insert(createRdata(RRType::RRSIG(), rrclass, ibuffer,
impl_->olddata_buffer_.getLength()));
if (!impl_->rrsigs_.insert(
createRdata(RRType::RRSIG(), rrclass, ibuffer,
impl_->olddata_buffer_.getLength())).second) {
isc_throw(Unexpected, "duplicate RRSIG found in merging RdataSet");
}
impl_->olddata_buffer_.clear();
}
impl_->old_sig_len_ = total_len;
......
......@@ -175,6 +175,17 @@ public:
/// for another attempt of encoding, which is unlikely), the caller can
/// modify or destroy the old data.
///
/// The caller must also ensure that \c old_data don't contain any
/// duplicate Rdata or RRSIG. Normally the caller doesn't have to do
/// anything special to meet this requirement, though, as the data
/// should have been generated by an \c RdataEncoder object before,
/// which guarantees that condition. But this method checks the
/// assumption in case it was crafted or otherwise broken data, and
/// throws an exception if that is the case.
///
/// \throw Unexpected Given encoded data contain duplicate Rdata or RRSIG
/// (normally shouldn't happen, see the description).
///
/// \param rrclass The RR class of RDATA to be encoded in the session.
/// \param rrtype The RR type of RDATA to be encoded in the session.
/// \param old_data Point to previously encoded data for the same RR
......
......@@ -1003,6 +1003,33 @@ TYPED_TEST(RdataEncodeDecodeTest, mergeRdata) {
this->mergeRdataCommon(old_rrsigs, rrsigs);
}
TEST_F(RdataSerializationTest, mergeRdataFromDuplicate) {
// create encoded data containing duplicate Rdata and try to start a
// new encoding session in the merge mode with that data. It breaks the
// assumption and should result in an exception.
const uint8_t data[] = { 192, 0, 2, 1, 192, 0, 2, 1 };
EXPECT_THROW(encoder_.start(RRClass::IN(), RRType::A(), data, 2, 0),
isc::Unexpected);
// Same for duplicate RRSIG
isc::util::OutputBuffer buffer(0);
vector<uint8_t> sigdata;
rrsig_rdata_->toWire(buffer);
const uint16_t sig_len = buffer.getLength();
// Encode lengths of RRSIGs, 2 bytes each, in host byte order
const uint8_t* const lp = static_cast<const uint8_t*>(
static_cast<const void*>(&sig_len));
sigdata.insert(sigdata.end(), lp, lp + sizeof(sig_len));
sigdata.insert(sigdata.end(), lp, lp + sizeof(sig_len));
// then the RRSIG data
const uint8_t* const dp = static_cast<const uint8_t*>(buffer.getData());
sigdata.insert(sigdata.end(), dp, dp + sig_len);
sigdata.insert(sigdata.end(), dp, dp + sig_len);
EXPECT_THROW(encoder_.start(RRClass::IN(), RRType::A(), &sigdata[0], 0, 2),
isc::Unexpected);
}
void
checkSigData(const ConstRdataPtr& decoded, bool* called, const void* encoded,
size_t length)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment