aboutsummaryrefslogtreecommitdiffstats
path: root/document
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@yahooinc.com>2023-01-25 09:48:25 +0000
committerTor Brede Vekterli <vekterli@yahooinc.com>2023-01-25 09:51:23 +0000
commit0d886192fdbb1c07776019da6c8a97e7f5aa0c61 (patch)
treee307aa7ee7c04a100c151bc00d2464bd4127e497 /document
parentf1d32c60a23ad9b8dc5223fefac0b14020ba49fa (diff)
Improve handling of corrupted serialized document data
Diffstat (limited to 'document')
-rw-r--r--document/src/vespa/document/serialization/vespadocumentdeserializer.cpp26
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)