diff --git a/src/types.cpp b/src/types.cpp index a3f691e9..1bffafd9 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -110,63 +110,63 @@ void DataBuf::reset() { uint8_t Exiv2::DataBuf::read_uint8(size_t offset) const { if (offset >= pData_.size()) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint8"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::read_uint8"); } return pData_[offset]; } void Exiv2::DataBuf::write_uint8(size_t offset, uint8_t x) { if (offset >= pData_.size()) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint8"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::write_uint8"); } pData_[offset] = x; } uint16_t Exiv2::DataBuf::read_uint16(size_t offset, ByteOrder byteOrder) const { if (pData_.size() < 2 || offset > (pData_.size() - 2)) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint16"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::read_uint16"); } return getUShort(&pData_[offset], byteOrder); } void Exiv2::DataBuf::write_uint16(size_t offset, uint16_t x, ByteOrder byteOrder) { if (pData_.size() < 2 || offset > (pData_.size() - 2)) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint16"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::write_uint16"); } us2Data(&pData_[offset], x, byteOrder); } uint32_t Exiv2::DataBuf::read_uint32(size_t offset, ByteOrder byteOrder) const { if (pData_.size() < 4 || offset > (pData_.size() - 4)) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint32"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::read_uint32"); } return getULong(&pData_[offset], byteOrder); } void Exiv2::DataBuf::write_uint32(size_t offset, uint32_t x, ByteOrder byteOrder) { if (pData_.size() < 4 || offset > (pData_.size() - 4)) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint32"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::write_uint32"); } ul2Data(&pData_[offset], x, byteOrder); } uint64_t Exiv2::DataBuf::read_uint64(size_t offset, ByteOrder byteOrder) const { if (pData_.size() < 8 || offset > (pData_.size() - 8)) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::read_uint64"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::read_uint64"); } return getULongLong(&pData_[offset], byteOrder); } void Exiv2::DataBuf::write_uint64(size_t offset, uint64_t x, ByteOrder byteOrder) { if (pData_.size() < 8 || offset > (pData_.size() - 8)) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::write_uint64"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::write_uint64"); } ull2Data(&pData_[offset], x, byteOrder); } int Exiv2::DataBuf::cmpBytes(size_t offset, const void* buf, size_t bufsize) const { if (pData_.size() < bufsize || offset > pData_.size() - bufsize) { - throw std::overflow_error("Overflow in Exiv2::DataBuf::cmpBytes"); + throw std::out_of_range("Overflow in Exiv2::DataBuf::cmpBytes"); } return memcmp(&pData_[offset], buf, bufsize); } diff --git a/unitTests/test_types.cpp b/unitTests/test_types.cpp index ba77a11c..dba9e04f 100644 --- a/unitTests/test_types.cpp +++ b/unitTests/test_types.cpp @@ -40,18 +40,61 @@ TEST(DataBuf, allocatesDataWithNonEmptyConstructor) { } TEST(DataBuf, canBeConstructedFromExistingData) { - const std::array data {'h', 'o', 'l', 'a'}; + const std::array data{'h', 'o', 'l', 'a'}; DataBuf instance(data.data(), data.size()); ASSERT_TRUE(std::equal(data.begin(), data.end(), instance.begin())); } TEST(DataBuf, tryingToAccessTooFarElementThrows) { - const std::array data {'h', 'o', 'l', 'a'}; + const std::array data{'h', 'o', 'l', 'a'}; DataBuf instance(data.data(), data.size()); ASSERT_THROW([[maybe_unused]] auto d = instance.data(4), std::out_of_range); ASSERT_THROW([[maybe_unused]] auto d = instance.c_data(4), std::out_of_range); } +TEST(DataBuf, read_uintFunctionsWorksOnExistingData) { + const std::array data{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + DataBuf instance(data.data(), data.size()); + ASSERT_EQ(data[0], instance.read_uint8(0)); + ASSERT_EQ(data[1], instance.read_uint16(0, bigEndian)); + ASSERT_EQ(0x00010203, instance.read_uint32(0, bigEndian)); + ASSERT_EQ(0x0001020304050607, instance.read_uint64(0, bigEndian)); +} + +TEST(DataBuf, read_uintFunctionsThrowsOnTooFarElements) { + const std::array data{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + DataBuf instance(data.data(), data.size()); + ASSERT_THROW([[maybe_unused]] auto d = instance.read_uint8(data.size()), std::out_of_range); + ASSERT_THROW([[maybe_unused]] auto d = instance.read_uint16(data.size(), bigEndian), std::out_of_range); + ASSERT_THROW([[maybe_unused]] auto d = instance.read_uint32(data.size(), bigEndian), std::out_of_range); + ASSERT_THROW([[maybe_unused]] auto d = instance.read_uint64(data.size(), bigEndian), std::out_of_range); +} + +TEST(DataBuf, write_uintFunctionsWorksWhenThereIsEnoughData) { + DataBuf instance(8); + std::uint64_t val{0x0102030405060708}; + ASSERT_NO_THROW(instance.write_uint8(0, (val >> 56))); + ASSERT_EQ(0x01, instance.read_uint8(0)); + + ASSERT_NO_THROW(instance.write_uint16(0, (val >> 48), bigEndian)); + ASSERT_EQ(0x0102, instance.read_uint16(0, bigEndian)); + + ASSERT_NO_THROW(instance.write_uint32(0, (val >> 32), bigEndian)); + ASSERT_EQ(0x01020304, instance.read_uint32(0, bigEndian)); + + ASSERT_NO_THROW(instance.write_uint64(0, val, bigEndian)); + ASSERT_EQ(val, instance.read_uint64(0, bigEndian)); +} + +TEST(DataBuf, write_uintFunctionsThrowsIfTryingToWriteOutOfBounds) { + DataBuf instance(8); + std::uint64_t val{0x0102030405060708}; + ASSERT_THROW(instance.write_uint8(8, (val >> 56)), std::out_of_range); + ASSERT_THROW(instance.write_uint16(7, (val >> 48), bigEndian), std::out_of_range); + ASSERT_THROW(instance.write_uint32(5, (val >> 32), bigEndian), std::out_of_range); + ASSERT_THROW(instance.write_uint64(1, (val >> 32), bigEndian), std::out_of_range); +} + // Test methods like DataBuf::read_uint32 and DataBuf::write_uint32. TEST(DataBuf, read_write_endianess) { DataBuf buf(4 + 1 + 2 + 4 + 8);