From 14fe7d17060b2e12203ed4b1fbfe44dd5aa606ec Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Mon, 19 Sep 2022 10:02:56 +0200 Subject: LoadCompactBinary gracefully handles read failures and sizes larger than the archive (#165) * add failing test * CompactBinary: Fixed LoadCompactBinary to gracefully handle read failures and sizes larger than the archive From https://p4-swarm.epicgames.net/changes/21983905 * changelog --- zencore/compactbinary.cpp | 52 +++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'zencore/compactbinary.cpp') diff --git a/zencore/compactbinary.cpp b/zencore/compactbinary.cpp index 375a97fc5..0e4a46fa1 100644 --- a/zencore/compactbinary.cpp +++ b/zencore/compactbinary.cpp @@ -1355,39 +1355,42 @@ LoadCompactBinary(BinaryReader& Ar, BufferAllocator Allocator) CbFieldType FieldType; uint64_t FieldSize = 1; - // Read in small increments until the total field size is known, to avoid reading too far. - for (;;) + for (const int64_t StartPos = Ar.CurrentOffset(); FieldSize > 0;) { - const int32_t ReadSize = int32_t(FieldSize - HeaderBytes.size()); - const size_t ReadOffset = HeaderBytes.size(); + // Read in small increments until the total field size is known, to avoid reading too far. + const int32_t ReadSize = int32_t(FieldSize - HeaderBytes.size()); + if (Ar.CurrentOffset() + ReadSize > Ar.GetSize()) + { + break; + } + + const size_t ReadOffset = HeaderBytes.size(); HeaderBytes.resize(ReadOffset + ReadSize); Ar.Read(HeaderBytes.data() + ReadOffset, ReadSize); if (TryMeasureCompactBinary(MakeMemoryView(HeaderBytes), FieldType, FieldSize)) { + if (FieldSize <= uint64_t(Ar.Size() - StartPos)) + { + UniqueBuffer Buffer = Allocator(FieldSize); + ZEN_ASSERT(Buffer.GetSize() == FieldSize); + MutableMemoryView View = Buffer.GetMutableView(); + memcpy(View.GetData(), HeaderBytes.data(), HeaderBytes.size()); + View.RightChopInline(HeaderBytes.size()); + if (!View.IsEmpty()) + { + // Read the remainder of the field. + Ar.Read(View.GetData(), View.GetSize()); + } + if (ValidateCompactBinary(Buffer, CbValidateMode::Default) == CbValidateError::None) + { + return CbField(SharedBuffer(std::move(Buffer))); + } + } break; } - if (FieldSize == 0) - { - return CbField(); - } } - - // Allocate the buffer, copy the header, and read the remainder of the field. - UniqueBuffer Buffer = Allocator(FieldSize); - ZEN_ASSERT(Buffer.GetSize() == FieldSize); - MutableMemoryView View = Buffer.GetMutableView(); - memcpy(View.GetData(), HeaderBytes.data(), HeaderBytes.size()); - View.RightChopInline(HeaderBytes.size()); - if (!View.IsEmpty()) - { - Ar.Read(View.GetData(), View.GetSize()); - } - if (ValidateCompactBinary(Buffer, CbValidateMode::Default) != CbValidateError::None) - { - return CbField(); - } - return CbField(SharedBuffer(std::move(Buffer))); + return CbField(); } CbObject @@ -2290,6 +2293,7 @@ TEST_CASE("json.uson") CHECK(Cb["value"sv].AsHash() == Hash); } } + #endif } // namespace zen -- cgit v1.2.3