diff options
author | Tor Brede Vekterli <vekterli@yahooinc.com> | 2023-01-25 09:48:25 +0000 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahooinc.com> | 2023-01-25 09:51:23 +0000 |
commit | 0d886192fdbb1c07776019da6c8a97e7f5aa0c61 (patch) | |
tree | e307aa7ee7c04a100c151bc00d2464bd4127e497 /document | |
parent | f1d32c60a23ad9b8dc5223fefac0b14020ba49fa (diff) |
Improve handling of corrupted serialized document data
Diffstat (limited to 'document')
-rw-r--r-- | document/src/vespa/document/serialization/vespadocumentdeserializer.cpp | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/document/src/vespa/document/serialization/vespadocumentdeserializer.cpp b/document/src/vespa/document/serialization/vespadocumentdeserializer.cpp index c8074b27549..b09896c2460 100644 --- a/document/src/vespa/document/serialization/vespadocumentdeserializer.cpp +++ b/document/src/vespa/document/serialization/vespadocumentdeserializer.cpp @@ -304,6 +304,10 @@ readFieldInfo(nbostream& input, SerializableArray::EntryMap & field_info) { for (size_t i = 0; i < field_count; ++i) { const uint32_t id = getInt1_4Bytes(input); const uint32_t size = getInt2_4_8Bytes(input); + if (size_t(offset) + size > input.size()) [[unlikely]] { + throw DeserializeException(fmt("Field (id=%u, offset=%u, size=%u) extends beyond remaining buffer size (%zu)", + id, offset, size, input.size()), VESPA_STRLOC); + } field_info.emplace_back(id, size, offset); offset += size; } @@ -344,25 +348,25 @@ void VespaDocumentDeserializer::readStructNoReset(StructFieldValue &value) { size_t data_size = readValue<uint32_t>(_stream); - CompressionConfig::Type compression_type = CompressionConfig::Type(readValue<uint8_t>(_stream)); + const auto compression_type = CompressionConfig::Type(readValue<uint8_t>(_stream)); + const bool is_compressed = CompressionConfig::isCompressed(compression_type); - SerializableArray::EntryMap field_info; + SerializableArray::EntryMap field_info; size_t uncompressed_size = 0; - if (CompressionConfig::isCompressed(compression_type)) { + if (is_compressed) { uncompressed_size = getInt2_4_8Bytes(_stream); } readFieldInfo(_stream, field_info); - if (CompressionConfig::isCompressed(compression_type)) { - if ((compression_type != CompressionConfig::LZ4)) { - throw DeserializeException("Unsupported compression type.", VESPA_STRLOC); - } else if (data_size > _stream.size()) { - throw DeserializeException("Invalid compressed struct data.", VESPA_STRLOC); - } + if (is_compressed && (compression_type != CompressionConfig::LZ4)) [[unlikely]] { + throw DeserializeException(fmt("Unsupported compression type: %u", static_cast<uint8_t>(compression_type)), VESPA_STRLOC); + } + if (data_size > _stream.size()) [[unlikely]] { + throw DeserializeException(fmt("Struct size (%zu) is greater than remaining buffer size (%zu)", + data_size, _stream.size()), VESPA_STRLOC); } - if (data_size > 0) { - ByteBuffer buffer = CompressionConfig::isCompressed(compression_type) + ByteBuffer buffer = is_compressed ? deCompress(compression_type, uncompressed_size, ConstBufferRef(_stream.peek(), data_size)) : (_stream.isLongLivedBuffer() ? ByteBuffer(_stream.peek(), data_size) |