BIND 10 master, updated. f70ff164d003111eeb20a83f13073ab9a9a4a2b7 Merge branch 'trac2749'
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Jan 28 02:39:12 UTC 2014
The branch, master has been updated
via f70ff164d003111eeb20a83f13073ab9a9a4a2b7 (commit)
via 6b3bc78d60e4d8a430d8e9c2ad45c53930af2c7b (commit)
via 1685d98e142c2b5915d19bf17f4029459a922321 (commit)
via 04f5b145f2e0ea8fc4ad30b7222198a91b3e5189 (commit)
via 9eedd903b78552493ea8fd55f89b8a58b94398d1 (commit)
via 99fe38e5d0b65cfe32b03ccbd61d5e174e093a4f (commit)
via a071815cc23931803825f6323d88ed1253ddfca7 (commit)
via 44b85098852c11243059319d4a75a124339e17d0 (commit)
via 45809d98ad9b62de6a0736d138547913d808a10e (commit)
via c7aeb4bec30cf6373e77216058174d6d35850dde (commit)
via d58433297eb07de97a7713dab8fbedbe46b1be3c (commit)
from 73179cbc2030af0c6a6298874161386613e0b9f9 (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 f70ff164d003111eeb20a83f13073ab9a9a4a2b7
Merge: 73179cb 6b3bc78
Author: Mukund Sivaraman <muks at isc.org>
Date: Tue Jan 28 07:57:56 2014 +0530
Merge branch 'trac2749'
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp6/dhcp6_srv.cc | 20 ++++++-----
src/lib/asiodns/io_fetch.cc | 2 +-
src/lib/asiodns/tests/io_fetch_unittest.cc | 8 +++--
src/lib/asiolink/tcp_socket.h | 2 +-
src/lib/asiolink/tests/tcp_socket_unittest.cc | 8 ++---
src/lib/asiolink/tests/udp_socket_unittest.cc | 2 +-
src/lib/dhcp/libdhcp++.cc | 8 ++---
src/lib/dhcp/option.cc | 27 ++++++--------
src/lib/dhcp/option4_addrlst.cc | 2 +-
src/lib/dhcp/option6_ia.cc | 6 ++--
src/lib/dhcp/option6_iaaddr.cc | 4 +--
src/lib/dhcp/option6_iaprefix.cc | 4 +--
src/lib/dhcp/option_data_types.h | 8 ++---
src/lib/dhcp/option_int.h | 6 ++--
src/lib/dhcp/option_int_array.h | 6 ++--
src/lib/dhcp/option_vendor.cc | 2 +-
.../resolve/tests/recursive_query_unittest_2.cc | 3 +-
.../resolve/tests/recursive_query_unittest_3.cc | 3 +-
src/lib/util/io_utilities.h | 37 +++++++++++++++++---
src/lib/util/tests/io_utilities_unittest.cc | 29 ++++++++++++---
20 files changed, 122 insertions(+), 65 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 16e44ac..7cdd2c9 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -646,10 +646,11 @@ Dhcpv6Srv::generateServerID() {
seconds -= DUID_TIME_EPOCH;
OptionBuffer srvid(8 + iface->getMacLen());
- writeUint16(DUID::DUID_LLT, &srvid[0]);
- writeUint16(HWTYPE_ETHERNET, &srvid[2]);
- writeUint32(static_cast<uint32_t>(seconds), &srvid[4]);
- memcpy(&srvid[0] + 8, iface->getMac(), iface->getMacLen());
+ // We know that the buffer is more than 8 bytes long at this point.
+ writeUint16(DUID::DUID_LLT, &srvid[0], 2);
+ writeUint16(HWTYPE_ETHERNET, &srvid[2], 2);
+ writeUint32(static_cast<uint32_t>(seconds), &srvid[4], 4);
+ memcpy(&srvid[8], iface->getMac(), iface->getMacLen());
serverid_ = OptionPtr(new Option(Option::V6, D6O_SERVERID,
srvid.begin(), srvid.end()));
@@ -662,8 +663,8 @@ Dhcpv6Srv::generateServerID() {
// See Section 9.3 of RFC3315 for details.
OptionBuffer srvid(12);
- writeUint16(DUID::DUID_EN, &srvid[0]);
- writeUint32(ENTERPRISE_ID_ISC, &srvid[2]);
+ writeUint16(DUID::DUID_EN, &srvid[0], srvid.size());
+ writeUint32(ENTERPRISE_ID_ISC, &srvid[2], srvid.size() - 2);
// Length of the identifier is company specific. I hereby declare
// ISC "standard" of 6 bytes long pseudo-random numbers.
@@ -2388,10 +2389,13 @@ Dhcpv6Srv::unpackOptions(const OptionBuffer& buf,
// The buffer being read comprises a set of options, each starting with
// a two-byte type code and a two-byte length field.
while (offset + 4 <= length) {
- uint16_t opt_type = isc::util::readUint16(&buf[offset]);
+ // At this point, from the while condition, we know that there
+ // are at least 4 bytes available following offset in the
+ // buffer.
+ uint16_t opt_type = isc::util::readUint16(&buf[offset], 2);
offset += 2;
- uint16_t opt_len = isc::util::readUint16(&buf[offset]);
+ uint16_t opt_len = isc::util::readUint16(&buf[offset], 2);
offset += 2;
if (offset + opt_len > length) {
diff --git a/src/lib/asiodns/io_fetch.cc b/src/lib/asiodns/io_fetch.cc
index a09d8df..aef7c57 100644
--- a/src/lib/asiodns/io_fetch.cc
+++ b/src/lib/asiodns/io_fetch.cc
@@ -162,7 +162,7 @@ struct IOFetchData {
// we sent.
bool responseOK() {
return (*remote_snd == *remote_rcv && cumulative >= 2 &&
- readUint16(received->getData()) == qid);
+ readUint16(received->getData(), received->getLength()) == qid);
}
};
diff --git a/src/lib/asiodns/tests/io_fetch_unittest.cc b/src/lib/asiodns/tests/io_fetch_unittest.cc
index acb184c..7f79a52 100644
--- a/src/lib/asiodns/tests/io_fetch_unittest.cc
+++ b/src/lib/asiodns/tests/io_fetch_unittest.cc
@@ -280,7 +280,8 @@ public:
cumulative_ += length;
bool complete = false;
if (cumulative_ > 2) {
- uint16_t dns_length = readUint16(receive_buffer_);
+ uint16_t dns_length = readUint16(receive_buffer_,
+ sizeof(receive_buffer_));
complete = ((dns_length + 2) == cumulative_);
}
@@ -310,7 +311,10 @@ public:
send_buffer_.clear();
send_buffer_.push_back(0);
send_buffer_.push_back(0);
- writeUint16(return_data_.size(), &send_buffer_[0]);
+ // send_buffer_.capacity() seems more logical below, but the
+ // code above fills in the first two bytes and size() becomes 2
+ // (sizeof uint16_t).
+ writeUint16(return_data_.size(), &send_buffer_[0], send_buffer_.size());
copy(return_data_.begin(), return_data_.end(), back_inserter(send_buffer_));
if (return_data_.size() >= 2) {
send_buffer_[2] = qid_0;
diff --git a/src/lib/asiolink/tcp_socket.h b/src/lib/asiolink/tcp_socket.h
index 7df4a80..18eca95 100644
--- a/src/lib/asiolink/tcp_socket.h
+++ b/src/lib/asiolink/tcp_socket.h
@@ -358,7 +358,7 @@ TCPSocket<C>::processReceivedData(const void* staging, size_t length,
}
// Have enough data to interpret the packet count, so do so now.
- expected = isc::util::readUint16(data);
+ expected = isc::util::readUint16(data, cumulative);
// We have two bytes less of data to process. Point to the start of the
// data and adjust the packet size. Note that at this point,
diff --git a/src/lib/asiolink/tests/tcp_socket_unittest.cc b/src/lib/asiolink/tests/tcp_socket_unittest.cc
index 9de366c..b0adf2e 100644
--- a/src/lib/asiolink/tests/tcp_socket_unittest.cc
+++ b/src/lib/asiolink/tests/tcp_socket_unittest.cc
@@ -227,7 +227,7 @@ serverRead(tcp::socket& socket, TCPCallback& server_cb) {
// If we have read at least two bytes, we can work out how much we
// should be reading.
if (server_cb.cumulative() >= 2) {
- server_cb.expected() = readUint16(server_cb.data());
+ server_cb.expected() = readUint16(server_cb.data(), server_cb.length());
if ((server_cb.expected() + 2) == server_cb.cumulative()) {
// Amount of data read from socket equals the size of the
@@ -261,7 +261,7 @@ TEST(TCPSocket, processReceivedData) {
}
// Check that the method will handle various receive sizes.
- writeUint16(PACKET_SIZE, inbuff);
+ writeUint16(PACKET_SIZE, inbuff, sizeof(inbuff));
cumulative = 0;
offset = 0;
@@ -317,7 +317,7 @@ TEST(TCPSocket, processReceivedData) {
// Tests the operation of a TCPSocket by opening it, sending an asynchronous
// message to a server, receiving an asynchronous message from the server and
// closing.
-TEST(TCPSocket, SequenceTest) {
+TEST(TCPSocket, sequenceTest) {
// Common objects.
IOService service; // Service object for async control
@@ -408,7 +408,7 @@ TEST(TCPSocket, SequenceTest) {
server_cb.length() = 0;
server_cb.cumulative() = 0;
- writeUint16(sizeof(INBOUND_DATA), server_cb.data());
+ writeUint16(sizeof(INBOUND_DATA), server_cb.data(), TCPCallback::MIN_SIZE);
copy(INBOUND_DATA, (INBOUND_DATA + sizeof(INBOUND_DATA) - 1),
(server_cb.data() + 2));
server_socket.async_send(asio::buffer(server_cb.data(),
diff --git a/src/lib/asiolink/tests/udp_socket_unittest.cc b/src/lib/asiolink/tests/udp_socket_unittest.cc
index 3d91874..be62590 100644
--- a/src/lib/asiolink/tests/udp_socket_unittest.cc
+++ b/src/lib/asiolink/tests/udp_socket_unittest.cc
@@ -188,7 +188,7 @@ TEST(UDPSocket, processReceivedData) {
// two bytes of the buffer.
uint16_t count = 0;
for (uint32_t i = 0; i < (2 << 16); ++i, ++count) {
- writeUint16(count, inbuff);
+ writeUint16(count, inbuff, sizeof(inbuff));
// Set some random values
cumulative = 5;
diff --git a/src/lib/dhcp/libdhcp++.cc b/src/lib/dhcp/libdhcp++.cc
index f6ba978..f55f6bc 100644
--- a/src/lib/dhcp/libdhcp++.cc
+++ b/src/lib/dhcp/libdhcp++.cc
@@ -231,10 +231,10 @@ size_t LibDHCP::unpackOptions6(const OptionBuffer& buf,
// The buffer being read comprises a set of options, each starting with
// a two-byte type code and a two-byte length field.
while (offset + 4 <= length) {
- uint16_t opt_type = isc::util::readUint16(&buf[offset]);
+ uint16_t opt_type = isc::util::readUint16(&buf[offset], 2);
offset += 2;
- uint16_t opt_len = isc::util::readUint16(&buf[offset]);
+ uint16_t opt_len = isc::util::readUint16(&buf[offset], 2);
offset += 2;
if (offset + opt_len > length) {
@@ -413,10 +413,10 @@ size_t LibDHCP::unpackVendorOptions6(const uint32_t vendor_id,
// The buffer being read comprises a set of options, each starting with
// a two-byte type code and a two-byte length field.
while (offset + 4 <= length) {
- uint16_t opt_type = isc::util::readUint16(&buf[offset]);
+ uint16_t opt_type = isc::util::readUint16(&buf[offset], 2);
offset += 2;
- uint16_t opt_len = isc::util::readUint16(&buf[offset]);
+ uint16_t opt_len = isc::util::readUint16(&buf[offset], 2);
offset += 2;
if (offset + opt_len > length) {
diff --git a/src/lib/dhcp/option.cc b/src/lib/dhcp/option.cc
index f5ab75e..24ddc06 100644
--- a/src/lib/dhcp/option.cc
+++ b/src/lib/dhcp/option.cc
@@ -250,35 +250,28 @@ uint8_t Option::getUint8() {
}
uint16_t Option::getUint16() {
- if (data_.size() < sizeof(uint16_t) ) {
- isc_throw(OutOfRange, "Attempt to read uint16 from option " << type_
- << " that has size " << data_.size());
- }
-
- return ( readUint16(&data_[0]) );
+ // readUint16() checks and throws OutOfRange if data_ is too small.
+ return (readUint16(&data_[0], data_.size()));
}
uint32_t Option::getUint32() {
- if (data_.size() < sizeof(uint32_t) ) {
- isc_throw(OutOfRange, "Attempt to read uint32 from option " << type_
- << " that has size " << data_.size());
- }
- return ( readUint32(&data_[0]) );
+ // readUint32() checks and throws OutOfRange if data_ is too small.
+ return (readUint32(&data_[0], data_.size()));
}
void Option::setUint8(uint8_t value) {
- data_.resize(1);
- data_[0] = value;
+ data_.resize(sizeof(value));
+ data_[0] = value;
}
void Option::setUint16(uint16_t value) {
- data_.resize(2);
- writeUint16(value, &data_[0]);
+ data_.resize(sizeof(value));
+ writeUint16(value, &data_[0], data_.size());
}
void Option::setUint32(uint32_t value) {
- data_.resize(4);
- writeUint32(value, &data_[0]);
+ data_.resize(sizeof(value));
+ writeUint32(value, &data_[0], data_.size());
}
bool Option::equal(const OptionPtr& other) const {
diff --git a/src/lib/dhcp/option4_addrlst.cc b/src/lib/dhcp/option4_addrlst.cc
index 436d07d..223da16 100644
--- a/src/lib/dhcp/option4_addrlst.cc
+++ b/src/lib/dhcp/option4_addrlst.cc
@@ -53,7 +53,7 @@ Option4AddrLst::Option4AddrLst(uint8_t type, OptionBufferConstIter first,
while (first != last) {
const uint8_t* ptr = &(*first);
- addAddress(IOAddress(readUint32(ptr)));
+ addAddress(IOAddress(readUint32(ptr, distance(first, last))));
first += V4ADDRESS_LEN;
}
}
diff --git a/src/lib/dhcp/option6_ia.cc b/src/lib/dhcp/option6_ia.cc
index 825a5bf..a5751dd 100644
--- a/src/lib/dhcp/option6_ia.cc
+++ b/src/lib/dhcp/option6_ia.cc
@@ -72,12 +72,12 @@ void Option6IA::unpack(OptionBufferConstIter begin,
if (distance(begin, end) < OPTION6_IA_LEN) {
isc_throw(OutOfRange, "Option " << type_ << " truncated");
}
- iaid_ = readUint32( &(*begin) );
+ iaid_ = readUint32(&(*begin), distance(begin, end));
begin += sizeof(uint32_t);
- t1_ = readUint32( &(*begin) );
+ t1_ = readUint32(&(*begin), distance(begin, end));
begin += sizeof(uint32_t);
- t2_ = readUint32( &(*begin) );
+ t2_ = readUint32(&(*begin), distance(begin, end));
begin += sizeof(uint32_t);
unpackOptions(OptionBuffer(begin, end));
diff --git a/src/lib/dhcp/option6_iaaddr.cc b/src/lib/dhcp/option6_iaaddr.cc
index cbcd555..9e02be7 100644
--- a/src/lib/dhcp/option6_iaaddr.cc
+++ b/src/lib/dhcp/option6_iaaddr.cc
@@ -78,10 +78,10 @@ void Option6IAAddr::unpack(OptionBuffer::const_iterator begin,
addr_ = IOAddress::fromBytes(AF_INET6, &(*begin));
begin += V6ADDRESS_LEN;
- preferred_ = readUint32( &(*begin) );
+ preferred_ = readUint32(&(*begin), distance(begin, end));
begin += sizeof(uint32_t);
- valid_ = readUint32( &(*begin) );
+ valid_ = readUint32(&(*begin), distance(begin, end));
begin += sizeof(uint32_t);
unpackOptions(OptionBuffer(begin, end));
diff --git a/src/lib/dhcp/option6_iaprefix.cc b/src/lib/dhcp/option6_iaprefix.cc
index d28b4f7..357942f 100644
--- a/src/lib/dhcp/option6_iaprefix.cc
+++ b/src/lib/dhcp/option6_iaprefix.cc
@@ -76,10 +76,10 @@ void Option6IAPrefix::unpack(OptionBuffer::const_iterator begin,
isc_throw(OutOfRange, "Option " << type_ << " truncated");
}
- preferred_ = readUint32( &(*begin) );
+ preferred_ = readUint32(&(*begin), distance(begin, end));
begin += sizeof(uint32_t);
- valid_ = readUint32( &(*begin) );
+ valid_ = readUint32(&(*begin), distance(begin, end));
begin += sizeof(uint32_t);
prefix_len_ = *begin;
diff --git a/src/lib/dhcp/option_data_types.h b/src/lib/dhcp/option_data_types.h
index d9d8a52..fb4d101 100644
--- a/src/lib/dhcp/option_data_types.h
+++ b/src/lib/dhcp/option_data_types.h
@@ -298,12 +298,12 @@ public:
case 2:
// Calling readUint16 works either for unsigned
// or signed types.
- value = isc::util::readUint16(&(*buf.begin()));
+ value = isc::util::readUint16(&(*buf.begin()), buf.size());
break;
case 4:
// Calling readUint32 works either for unsigned
// or signed types.
- value = isc::util::readUint32(&(*buf.begin()));
+ value = isc::util::readUint32(&(*buf.begin()), buf.size());
break;
default:
// This should not happen because we made checks on data types
@@ -331,11 +331,11 @@ public:
break;
case 2:
buf.resize(buf.size() + 2);
- isc::util::writeUint16(static_cast<uint16_t>(value), &buf[buf.size() - 2]);
+ isc::util::writeUint16(static_cast<uint16_t>(value), &buf[buf.size() - 2], 2);
break;
case 4:
buf.resize(buf.size() + 4);
- isc::util::writeUint32(static_cast<uint32_t>(value), &buf[buf.size() - 4]);
+ isc::util::writeUint32(static_cast<uint32_t>(value), &buf[buf.size() - 4], 4);
break;
default:
// The cases above cover whole range of possible data lengths because
diff --git a/src/lib/dhcp/option_int.h b/src/lib/dhcp/option_int.h
index cbdbcb0..f11b4eb 100644
--- a/src/lib/dhcp/option_int.h
+++ b/src/lib/dhcp/option_int.h
@@ -142,10 +142,12 @@ public:
value_ = *begin;
break;
case 2:
- value_ = isc::util::readUint16(&(*begin));
+ value_ = isc::util::readUint16(&(*begin),
+ std::distance(begin, end));
break;
case 4:
- value_ = isc::util::readUint32(&(*begin));
+ value_ = isc::util::readUint32(&(*begin),
+ std::distance(begin, end));
break;
default:
isc_throw(dhcp::InvalidDataType, "non-integer type");
diff --git a/src/lib/dhcp/option_int_array.h b/src/lib/dhcp/option_int_array.h
index e0e9356..62e121b 100644
--- a/src/lib/dhcp/option_int_array.h
+++ b/src/lib/dhcp/option_int_array.h
@@ -201,10 +201,12 @@ public:
values_.push_back(*begin);
break;
case 2:
- values_.push_back(isc::util::readUint16(&(*begin)));
+ values_.push_back(isc::util::readUint16(&(*begin),
+ std::distance(begin, end)));
break;
case 4:
- values_.push_back(isc::util::readUint32(&(*begin)));
+ values_.push_back(isc::util::readUint32(&(*begin),
+ std::distance(begin, end)));
break;
default:
isc_throw(dhcp::InvalidDataType, "non-integer type");
diff --git a/src/lib/dhcp/option_vendor.cc b/src/lib/dhcp/option_vendor.cc
index 878b534..0d5c550 100644
--- a/src/lib/dhcp/option_vendor.cc
+++ b/src/lib/dhcp/option_vendor.cc
@@ -54,7 +54,7 @@ void OptionVendor::unpack(OptionBufferConstIter begin,
<< ", length=" << distance(begin, end));
}
- vendor_id_ = isc::util::readUint32(&(*begin));
+ vendor_id_ = isc::util::readUint32(&(*begin), distance(begin, end));
OptionBuffer vendor_buffer(begin +4, end);
diff --git a/src/lib/resolve/tests/recursive_query_unittest_2.cc b/src/lib/resolve/tests/recursive_query_unittest_2.cc
index d6019d0..8c2e9e3 100644
--- a/src/lib/resolve/tests/recursive_query_unittest_2.cc
+++ b/src/lib/resolve/tests/recursive_query_unittest_2.cc
@@ -462,7 +462,8 @@ public:
tcp_cumulative_ += length;
bool complete = false;
if (tcp_cumulative_ > 2) {
- uint16_t dns_length = readUint16(tcp_receive_buffer_);
+ uint16_t dns_length = readUint16(tcp_receive_buffer_,
+ sizeof(tcp_receive_buffer_));
complete = ((dns_length + 2) == tcp_cumulative_);
}
diff --git a/src/lib/resolve/tests/recursive_query_unittest_3.cc b/src/lib/resolve/tests/recursive_query_unittest_3.cc
index 7803b88..acf60d6 100644
--- a/src/lib/resolve/tests/recursive_query_unittest_3.cc
+++ b/src/lib/resolve/tests/recursive_query_unittest_3.cc
@@ -336,7 +336,8 @@ public:
tcp_cumulative_ += length;
bool complete = false;
if (tcp_cumulative_ > 2) {
- uint16_t dns_length = readUint16(tcp_receive_buffer_);
+ uint16_t dns_length = readUint16(tcp_receive_buffer_,
+ sizeof(tcp_receive_buffer_));
complete = ((dns_length + 2) == tcp_cumulative_);
}
diff --git a/src/lib/util/io_utilities.h b/src/lib/util/io_utilities.h
index cd35364..4cfa999 100644
--- a/src/lib/util/io_utilities.h
+++ b/src/lib/util/io_utilities.h
@@ -15,6 +15,7 @@
#ifndef IO_UTILITIES_H
#define IO_UTILITIES_H
+#include <exceptions/exceptions.h>
#include <cstddef>
namespace isc {
@@ -28,10 +29,17 @@ namespace util {
/// \param buffer Data buffer at least two bytes long of which the first two
/// bytes are assumed to represent a 16-bit integer in network-byte
/// order.
+/// \param length Length of the data buffer.
///
/// \return Value of 16-bit integer
inline uint16_t
-readUint16(const void* buffer) {
+readUint16(const void* buffer, size_t length) {
+ if (length < sizeof(uint16_t)) {
+ isc_throw(isc::OutOfRange,
+ "Length (" << length << ") of buffer is insufficient " <<
+ "to read a uint16_t");
+ }
+
const uint8_t* byte_buffer = static_cast<const uint8_t*>(buffer);
uint16_t result = (static_cast<uint16_t>(byte_buffer[0])) << 8;
@@ -48,10 +56,17 @@ readUint16(const void* buffer) {
/// \param value 16-bit value to convert
/// \param buffer Data buffer at least two bytes long into which the 16-bit
/// value is written in network-byte order.
+/// \param length Length of the data buffer.
///
/// \return pointer to the next byte after stored value
inline uint8_t*
-writeUint16(uint16_t value, void* buffer) {
+writeUint16(uint16_t value, void* buffer, size_t length) {
+ if (length < sizeof(uint16_t)) {
+ isc_throw(isc::OutOfRange,
+ "Length (" << length << ") of buffer is insufficient " <<
+ "to write a uint16_t");
+ }
+
uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
byte_buffer[0] = static_cast<uint8_t>((value & 0xff00U) >> 8);
@@ -65,10 +80,17 @@ writeUint16(uint16_t value, void* buffer) {
/// \param buffer Data buffer at least four bytes long of which the first four
/// bytes are assumed to represent a 32-bit integer in network-byte
/// order.
+/// \param length Length of the data buffer.
///
/// \return Value of 32-bit unsigned integer
inline uint32_t
-readUint32(const uint8_t* buffer) {
+readUint32(const uint8_t* buffer, size_t length) {
+ if (length < sizeof(uint32_t)) {
+ isc_throw(isc::OutOfRange,
+ "Length (" << length << ") of buffer is insufficient " <<
+ "to read a uint32_t");
+ }
+
const uint8_t* byte_buffer = static_cast<const uint8_t*>(buffer);
uint32_t result = (static_cast<uint32_t>(byte_buffer[0])) << 24;
@@ -84,10 +106,17 @@ readUint32(const uint8_t* buffer) {
/// \param value 32-bit value to convert
/// \param buffer Data buffer at least four bytes long into which the 32-bit
/// value is written in network-byte order.
+/// \param length Length of the data buffer.
///
/// \return pointer to the next byte after stored value
inline uint8_t*
-writeUint32(uint32_t value, uint8_t* buffer) {
+writeUint32(uint32_t value, uint8_t* buffer, size_t length) {
+ if (length < sizeof(uint32_t)) {
+ isc_throw(isc::OutOfRange,
+ "Length (" << length << ") of buffer is insufficient " <<
+ "to write a uint32_t");
+ }
+
uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
byte_buffer[0] = static_cast<uint8_t>((value & 0xff000000U) >> 24);
diff --git a/src/lib/util/tests/io_utilities_unittest.cc b/src/lib/util/tests/io_utilities_unittest.cc
index 8e0c232..d7d3b0e 100644
--- a/src/lib/util/tests/io_utilities_unittest.cc
+++ b/src/lib/util/tests/io_utilities_unittest.cc
@@ -42,11 +42,15 @@ TEST(asioutil, readUint16) {
data[0] = i8;
data[1] = j8;
buffer.setPosition(0);
- EXPECT_EQ(buffer.readUint16(), readUint16(data));
+ EXPECT_EQ(buffer.readUint16(), readUint16(data, sizeof(data)));
}
}
}
+TEST(asioutil, readUint16OutOfRange) {
+ uint8_t data;
+ EXPECT_THROW(readUint16(&data, sizeof(data)), isc::OutOfRange);
+}
TEST(asioutil, writeUint16) {
@@ -64,7 +68,7 @@ TEST(asioutil, writeUint16) {
buffer.writeUint16(i16);
// ... and the test data
- writeUint16(i16, test);
+ writeUint16(i16, test, sizeof(test));
// ... and compare
const uint8_t* ref = static_cast<const uint8_t*>(buffer.getData());
@@ -73,6 +77,12 @@ TEST(asioutil, writeUint16) {
}
}
+TEST(asioutil, writeUint16OutOfRange) {
+ uint16_t i16 = 42;
+ uint8_t data;
+ EXPECT_THROW(writeUint16(i16, &data, sizeof(data)), isc::OutOfRange);
+}
+
// test data shared amount readUint32 and writeUint32 tests
const static uint32_t test32[] = {
0,
@@ -93,11 +103,15 @@ TEST(asioutil, readUint32) {
uint32_t tmp = htonl(test32[i]);
memcpy(&data[offset], &tmp, sizeof(uint32_t));
- EXPECT_EQ(test32[i], readUint32(&data[offset]));
+ EXPECT_EQ(test32[i], readUint32(&data[offset], sizeof(uint32_t)));
}
}
}
+TEST(asioutil, readUint32OutOfRange) {
+ uint8_t data[3];
+ EXPECT_THROW(readUint32(data, sizeof(data)), isc::OutOfRange);
+}
TEST(asioutil, writeUint32) {
uint8_t data[8];
@@ -107,7 +121,8 @@ TEST(asioutil, writeUint32) {
// it 4 times.
for (int offset=0; offset < 4; offset++) {
for (int i=0; i < sizeof(test32)/sizeof(uint32_t); i++) {
- uint8_t* ptr = writeUint32(test32[i], &data[offset]);
+ uint8_t* ptr = writeUint32(test32[i], &data[offset],
+ sizeof(uint32_t));
EXPECT_EQ(&data[offset]+sizeof(uint32_t), ptr);
@@ -117,3 +132,9 @@ TEST(asioutil, writeUint32) {
}
}
}
+
+TEST(asioutil, writeUint32OutOfRange) {
+ uint32_t i32 = 28;
+ uint8_t data[3];
+ EXPECT_THROW(writeUint32(i32, data, sizeof(data)), isc::OutOfRange);
+}
More information about the bind10-changes
mailing list