Commit 8553a206 authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[2148] add LabelSequence::extend() method

parent 6f60dbc9
......@@ -337,6 +337,46 @@ LabelSequence::toText() const {
return (toText(!isAbsolute()));
}
void
LabelSequence::extend(const LabelSequence& labels,
uint8_t buf[MAX_SERIALIZED_LENGTH])
{
// check whether this labelsequence appears to have anything to do with
// the given buf at all
if (data_ != buf || offsets_ != &buf[Name::MAX_WIRE]) {
isc_throw(BadValue,
"extend() called with unrelated buffer");
}
// check name does not become too long
size_t orig_len = getDataLength() - 1;
if (orig_len + labels.getDataLength() > Name::MAX_WIRE) {
isc_throw(BadValue,
"extend() would exceed maximum wire length");
}
// check offsets data does not become too long
if (getLabelCount() + labels.getLabelCount() > Name::MAX_LABELS) {
isc_throw(BadValue,
"extend() would exceed maximum number of labels");
}
// append second to first labelsequence
size_t data_len;
const uint8_t *data = labels.getData(&data_len);
memcpy(buf + orig_len, data, data_len);
// append offsets
for (size_t i = 0; i < labels.getLabelCount(); ++i) {
buf[Name::MAX_WIRE + last_label_ + i] =
offsets_[last_label_] +
labels.offsets_[i + labels.first_label_] -
labels.offsets_[labels.first_label_];
}
last_label_ += labels.last_label_ - labels.first_label_;
}
std::ostream&
operator<<(std::ostream& os, const LabelSequence& label_sequence) {
os << label_sequence.toText();
......
......@@ -103,6 +103,11 @@ public:
///
/// \note The given buf MUST remain in scope during the lifetime of
/// the LabelSequence created here.
/// \note The buffer should never be modified except through
/// calls to extend().
/// \note Also, only associate the buffer with at most one
/// LabelSequence. Behaviour is undefined if two LabelSequences are
/// using the same buffer.
///
/// \param src LabelSequence to copy the initial data from
/// \param buf external buffer to store this labelsequence's data in
......@@ -261,6 +266,29 @@ public:
/// \return a string representation of the <code>LabelSequence</code>.
std::string toText() const;
/// \brief Extend this LabelSequence with the given labelsequence
///
/// The given labels are added to the name data, and internal data
/// is updated accordingly.
/// The data from the given LabelSequence is copied into the buffer
/// associated with this LabelSequence; the appended LabelSequence
/// can be released if it is not needed for other operations anymore.
///
/// Some minimal checking is done on the data, but internal integrity
/// is not assumed. Do NOT modify the given buffer except through calls
/// to this method, and do NOT call this method if the buffer is
/// associated to another LabelSequence (behaviour of the other
/// LabelSequence is undefined in that scenario).
///
/// \exception BadValue If the buffer does not appear to be associated
/// with this LabelSequence, or if the maximum wire length or maximum
/// number of labels would be exceeded by this operation
///
/// \param labels The labels to append to this LabelSequence
/// \param buf The buffer associated with this LabelSequence
void extend(const LabelSequence& labels,
uint8_t buf[MAX_SERIALIZED_LENGTH]);
private:
/// \brief Convert the LabelSequence to a string.
///
......
......@@ -916,6 +916,95 @@ TEST(LabelSequence, extendableLabelSequenceRightStrippedSource) {
}
}
// Check some basic 'extend' functionality
TEST(LabelSequence, extend) {
Name n1("foo.bar.");
Name n2("foo");
Name n3("bar");
LabelSequence ls1(n1);
LabelSequence ls2(n2);
LabelSequence ls3(n3);
LabelSequence ls4(n1);
uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
memset(buf, 0, LabelSequence::MAX_SERIALIZED_LENGTH);
LabelSequence els(ls2, buf);
check_compare(ls1, els, isc::dns::NameComparisonResult::COMMONANCESTOR, 1);
els.extend(ls3, buf);
check_compare(ls1, els, isc::dns::NameComparisonResult::EQUAL, 3);
stripLeftCheck(ls1, els, ls4);
stripRightCheck(ls1, els, ls4);
els.extend(ls3, buf);
check_compare(ls1, ls2, isc::dns::NameComparisonResult::COMMONANCESTOR, 1);
}
// Check that when extending with itself, it does not cause horrible failures
TEST(LabelSequence, extendWithItself) {
Name n1("foo.bar.");
Name n2("foo.bar.foo.bar.");
LabelSequence ls1(n1);
LabelSequence ls2(n2);
uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
memset(buf, 0, LabelSequence::MAX_SERIALIZED_LENGTH);
LabelSequence els(ls1, buf);
std::cout << "[XX] " << els.toText() << std::endl;
// some men just want to watch the world burn.
els.extend(els, buf);
std::cout << "[XX] " << els.toText() << std::endl;
check_equal(ls2, els);
}
// Test that 'extending' with just a root label is a no-op
TEST(LabelSequence, extendWithRoot) {
Name n1("example.org");
LabelSequence ls1(n1);
uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
LabelSequence els(LabelSequence(ls1, buf));
check_equal(ls1, els);
els.extend(LabelSequence(Name(".")), buf);
check_equal(ls1, els);
}
// Check possible failure modes of extend()
TEST(LabelSequence, extendBadData) {
Name n1("example.org.");
LabelSequence ls1(n1);
uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
memset(buf, 0, LabelSequence::MAX_SERIALIZED_LENGTH);
LabelSequence els(ls1, buf);
// try use with unrelated labelsequence
EXPECT_THROW(ls1.extend(ls1, buf), isc::BadValue);
// Create a long name, but so that we can still extend once
Name longlabel("1234567890123456789012345678901234567890"
"12345678901234567890");
LabelSequence ls2(longlabel);
els = LabelSequence(ls2, buf);
els.extend(els, buf);
els.extend(ls2, buf);
els.extend(ls2, buf);
ASSERT_EQ(245, els.getDataLength());
// Extending once more with 10 bytes should still work
els.extend(LabelSequence(Name("123456789")), buf);
// But now, even the shortest extension should fail
EXPECT_THROW(els.extend(LabelSequence(Name("1")), buf), isc::BadValue);
// Also check that extending past MAX_LABELS is not possible
Name shortname("1.");
LabelSequence short_ls(shortname);
els = LabelSequence(short_ls, buf);
for (size_t i=0; i < 125; ++i) {
els.extend(short_ls, buf);
}
EXPECT_THROW(els.extend(short_ls, buf), isc::BadValue);
}
}
Supports Markdown
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