#ifndef IO_UTILITIES_H
#define IO_UTILITIES_H
+#include <exceptions/exceptions.h>
#include <cstddef>
namespace isc {
/// \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;
/// \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);
/// \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;
/// \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);
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) {
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());
}
}
+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,
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];
// 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);
}
}
}
+
+TEST(asioutil, writeUint32OutOfRange) {
+ uint32_t i32 = 28;
+ uint8_t data[3];
+ EXPECT_THROW(writeUint32(i32, data, sizeof (data)), isc::OutOfRange);
+}