From: Mukund Sivaraman Date: Fri, 10 Jan 2014 03:38:47 +0000 (+0530) Subject: [2749] Check sizes in memory access functions in io_utilities.h X-Git-Tag: bind10-1.2.0beta1-release~104^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d58433297eb07de97a7713dab8fbedbe46b1be3c;p=thirdparty%2Fkea.git [2749] Check sizes in memory access functions in io_utilities.h --- diff --git a/src/lib/util/io_utilities.h b/src/lib/util/io_utilities.h index cd35364f7c..82fd311beb 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 #include 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(buffer); uint16_t result = (static_cast(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(buffer); byte_buffer[0] = static_cast((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(buffer); uint32_t result = (static_cast(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(buffer); byte_buffer[0] = static_cast((value & 0xff000000U) >> 24); diff --git a/src/lib/util/tests/io_utilities_unittest.cc b/src/lib/util/tests/io_utilities_unittest.cc index 8e0c232d26..6c71123798 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(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,7 @@ 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 +131,9 @@ TEST(asioutil, writeUint32) { } } } + +TEST(asioutil, writeUint32OutOfRange) { + uint32_t i32 = 28; + uint8_t data[3]; + EXPECT_THROW(writeUint32(i32, data, sizeof (data)), isc::OutOfRange); +}