BIND 10 trac2312, updated. 2dd98a113773481b77ca0600c1d1028e2b5fdd72 [2312] Corrected typos in doxygen documentation.
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Nov 27 15:59:22 UTC 2012
The branch, trac2312 has been updated
via 2dd98a113773481b77ca0600c1d1028e2b5fdd72 (commit)
via 7cbe475737d43aaf4757b5df76d9bea75b0bf5a1 (commit)
from e4670244659f82b8fabdcaddce43d229a79f34f8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 2dd98a113773481b77ca0600c1d1028e2b5fdd72
Author: Marcin Siodelski <marcin at isc.org>
Date: Tue Nov 27 16:58:06 2012 +0100
[2312] Corrected typos in doxygen documentation.
commit 7cbe475737d43aaf4757b5df76d9bea75b0bf5a1
Author: Marcin Siodelski <marcin at isc.org>
Date: Tue Nov 27 16:52:51 2012 +0100
[2312] Report an error when option data is truncated.
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcp/option_custom.cc | 20 +++-
src/lib/dhcp/option_data_types.h | 4 +-
src/lib/dhcp/tests/option_custom_unittest.cc | 159 +++++++++++++++++++++++++-
3 files changed, 173 insertions(+), 10 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/option_custom.cc b/src/lib/dhcp/option_custom.cc
index b090f8f..6697587 100644
--- a/src/lib/dhcp/option_custom.cc
+++ b/src/lib/dhcp/option_custom.cc
@@ -78,12 +78,20 @@ OptionCustom::createBuffers() {
// are laid at the end).
if (data_size == 0) {
data_size = std::distance(data, data_.end());
- }
- // If we reached the end of buffer we assume that this option is
- // truncated because there is no remaining data to initialize
- // an option field.
- if (data_size == 0) {
- isc_throw(OutOfRange, "option buffer truncated");
+ if (data_size == 0) {
+ // If we reached the end of buffer we assume that this option is
+ // truncated because there is no remaining data to initialize
+ // an option field.
+ if (data_size == 0) {
+ isc_throw(OutOfRange, "option buffer truncated");
+ }
+ }
+ } else {
+ // Our data field requires that there is a certain chunk of
+ // data left in the buffer. If not, option is truncated.
+ if (std::distance(data, data_.end()) < data_size) {
+ isc_throw(OutOfRange, "option buffer truncated");
+ }
}
// Store the created buffer.
buffers.push_back(OptionBuffer(data, data + data_size));
diff --git a/src/lib/dhcp/option_data_types.h b/src/lib/dhcp/option_data_types.h
index 26e0cc4..d227749 100644
--- a/src/lib/dhcp/option_data_types.h
+++ b/src/lib/dhcp/option_data_types.h
@@ -216,7 +216,7 @@ public:
///
/// @param hex_str string representing a binary value encoded
/// with hexadecimal digits (without 0x prefix).
- /// @param [out] output buffer.
+ /// @param [out] buf output buffer.
static void writeBinary(const std::string& hex_str,
std::vector<uint8_t>& buf);
@@ -231,7 +231,7 @@ public:
/// The bool value is encoded in a buffer in such a way that
/// "1" means "true" and "0" means "false".
///
- /// @param boolean value to be written.
+ /// @param value boolean value to be written.
/// @param [out] buf output buffer.
static void writeBool(const bool value, std::vector<uint8_t>& buf);
diff --git a/src/lib/dhcp/tests/option_custom_unittest.cc b/src/lib/dhcp/tests/option_custom_unittest.cc
index bfde9e4..e26ff68 100644
--- a/src/lib/dhcp/tests/option_custom_unittest.cc
+++ b/src/lib/dhcp/tests/option_custom_unittest.cc
@@ -217,6 +217,46 @@ TEST_F(OptionCustomTest, int16Data) {
EXPECT_EQ(-234, value);
}
+// The purpose of this test is to verify that truncated option buffer
+// can't be used to form option holding an integer data.
+TEST_F(OptionCustomTest, int32DataTruncated) {
+ OptionDefinition opt_def("OPTION_FOO", 1000, "int32");
+
+ // Put two integer values into the buffer. One of
+ // them will be ignored by the option's constructor.
+ OptionBuffer buf;
+ writeInt<int32_t>(-234, buf);
+ writeInt<int32_t>(100, buf);
+
+ // Create custom option.
+ boost::scoped_ptr<OptionCustom> option;
+
+ // The length of the provided buffer is equal to 2*sizeof(uint32_t) so
+ // both values will be processed by constructor. Second one should be
+ // dropped.
+ EXPECT_NO_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 8));
+ );
+
+ // The option buffer's length is sufficient to keep only one uint32_t
+ // but this is ok since option needs only one value anyway.
+ EXPECT_NO_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 4));
+ );
+
+ // The option buffer's length is equal to sizeof(uint32_t) so it should
+ // be processed successfuly.
+ EXPECT_NO_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 4));
+ );
+
+ // The option bufferis now 1 byte too short. Expect exception being thrown.
+ EXPECT_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 3)),
+ isc::OutOfRange
+ );
+}
+
// The purpose of this test is to verify that the option definition comprising
// single IPv4 addres can be used to create an instance of custom option.
TEST_F(OptionCustomTest, ipv4AddressData) {
@@ -345,6 +385,45 @@ TEST_F(OptionCustomTest, booleanDataArray) {
EXPECT_TRUE(value4);
}
+// The purpose of this test is to verify that truncated buffer can't
+// be used to create an instance of the option which holds an array
+// of values.
+TEST_F(OptionCustomTest, uint16DataArrayTruncated) {
+ OptionDefinition opt_def("OPTION_FOO", 1000, "uint16", true);
+
+ OptionBuffer buf;
+ for (int i = 0; i < 3; ++i) {
+ writeInt<uint16_t>(i, buf);
+ }
+
+ // Create custom option using the input buffer.
+ boost::scoped_ptr<OptionCustom> option;
+
+ // Provide a buffer of a length of 4. This should succeed because exactly two
+ // uint16_t values fit into it.
+ EXPECT_NO_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 4));
+ );
+
+ // Provide a buffer of a length of 3. This should succeed because one uint16_t
+ // value fits into it despite the second one is truncated.
+ EXPECT_NO_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 3));
+ );
+
+ // Provide a buffer of a length of 2. This should succeed because still
+ // one uint16_t fits into it.
+ EXPECT_NO_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 2));
+ );
+
+ // Provide truncated buffer. This should cause the exception.
+ EXPECT_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 1)),
+ isc::OutOfRange
+ );
+}
+
// The purpose of this test is to verify that the option definition comprising
// an array of 32-bit signed integer values can be used to create an instance
// of custom option.
@@ -515,6 +594,54 @@ TEST_F(OptionCustomTest, recordData) {
EXPECT_EQ("ABCD", value4);
}
+// The purpose of this test is to verify that truncated buffer
+// can't be used to create an option being a record of value of
+// different types.
+TEST_F(OptionCustomTest, recordDataTruncated) {
+ // Create the definition of an option which comprises
+ // a record of fields of different types.
+ OptionDefinition opt_def("OPTION_FOO", 1000, "record");
+ ASSERT_NO_THROW(opt_def.addRecordField("uint16"));
+ ASSERT_NO_THROW(opt_def.addRecordField("ipv6-address"));
+ ASSERT_NO_THROW(opt_def.addRecordField("string"));
+
+ OptionBuffer buf;
+ // Initialize field 0.
+ writeInt<uint16_t>(8712, buf);
+ // Initialize field 1 to IPv6 address.
+ writeAddress(IOAddress("2001:db8:1::1"), buf);
+ // Initialize field 2 to string value.
+ writeString("ABCD", buf);
+
+ boost::scoped_ptr<OptionCustom> option;
+
+ // Constructor should not throw exception here because the length of the
+ // buffer meets the minimum length. The first 19 bytes hold data for
+ // all option fields: uint16, IPv4 address and first letter of string.
+ // Note that string will be truncated but this is acceptable because
+ // constructor have no way to determine the length of the original string.
+ EXPECT_NO_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 19));
+ );
+
+ // Reduce the buffer length by one byte should cause the constructor
+ // to fail. This is because 18 bytes can only hold first two data fields:
+ // 2 bytes of uint16_t value and IPv6 address. Option definitions specifies
+ // 3 data fields for this option but the length of the data is insufficient
+ // to initialize 3 data field.
+ EXPECT_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 18)),
+ isc::OutOfRange
+ );
+
+ // Try to further reduce the length of the buffer to make it insufficient
+ // to even initialize the second data field.
+ EXPECT_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf.begin(), buf.begin() + 17)),
+ isc::OutOfRange
+ );
+}
+
// The purpose of this test is to verify that pack function for
// DHCPv4 custom option works correctly.
TEST_F(OptionCustomTest, pack4) {
@@ -647,8 +774,7 @@ TEST_F(OptionCustomTest, unpack) {
// The purpose of this test is to verify that new data can be set for
// a custom option.
-TEST_F(OptionCustomTest, setData)
-{
+TEST_F(OptionCustomTest, setData) {
OptionDefinition opt_def("OPTION_FOO", 1000, "ipv6-address", true);
// Initialize reference data.
@@ -707,4 +833,33 @@ TEST_F(OptionCustomTest, setData)
}
}
+// The purpose of this test is to verify that an invalid index
+// value can't be used to access option data fields.
+TEST_F(OptionCustomTest, invalidIndex) {
+ OptionDefinition opt_def("OPTION_FOO", 999, "uint32", true);
+
+ OptionBuffer buf;
+ for (int i = 0; i < 10; ++i) {
+ writeInt<uint32_t>(i, buf);
+ }
+
+ // Use the input buffer to create custom option.
+ boost::scoped_ptr<OptionCustom> option;
+ ASSERT_NO_THROW(
+ option.reset(new OptionCustom(opt_def, Option::V6, buf));
+ );
+ ASSERT_TRUE(option);
+
+ // We expect that there are 10 uint32_t values stored in
+ // the option. The 10th element is accessed by index eq 9.
+ // Check that 9 is accepted.
+ EXPECT_NO_THROW(option->readInteger<uint32_t>(9));
+
+ // Check that index value beyond 9 is not accepted.
+ EXPECT_THROW(option->readInteger<uint32_t>(10), isc::OutOfRange);
+ EXPECT_THROW(option->readInteger<uint32_t>(11), isc::OutOfRange);
+}
+
+
+
} // anonymous namespace
More information about the bind10-changes
mailing list