Skip to content

Commit 92414f2

Browse files
author
Andrei Nasonov
committed
AI review: detect corruption in Free()/PopFront()
1 parent 42a55f0 commit 92414f2

2 files changed

Lines changed: 55 additions & 6 deletions

File tree

cloud/storage/core/libs/file_backed_containers/file_ring_buffer.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -521,16 +521,16 @@ class TFileRingBuffer::TImpl
521521

522522
TResultOrError<char*> Alloc(size_t size)
523523
{
524+
if (!ValidateAccess("Alloc")) {
525+
return MakeBufferIsCorruptError();
526+
}
527+
524528
if (CurrentAllocation.HasValue()) {
525529
return MakeError(
526530
E_INVALID_STATE,
527531
"Previous allocation is not committed");
528532
}
529533

530-
if (!ValidateAccess("Alloc")) {
531-
return MakeBufferIsCorruptError();
532-
}
533-
534534
if (size == 0) {
535535
return MakeError(
536536
E_ARGUMENT,
@@ -626,7 +626,12 @@ class TFileRingBuffer::TImpl
626626
CurrentAllocation.ActualPos,
627627
CurrentAllocation.Header);
628628

629-
Y_ABORT_UNLESS(written);
629+
if (!written) {
630+
SetCorrupted(
631+
TStringBuilder() << "Cannot write entry header at "
632+
<< CurrentAllocation.ActualPos);
633+
return MakeBufferIsCorruptError();
634+
}
630635

631636
// A compiler-only fence is sufficient here because there is no
632637
// concurrent access to the memory and we just need to ensure
@@ -657,12 +662,25 @@ class TFileRingBuffer::TImpl
657662
auto eh = Data()->ReadEntryHeader(it->second);
658663
eh.DataChecksum = 0;
659664
eh.FreeFlag = true;
660-
Data()->WriteEntryHeader(it->second, eh);
665+
666+
bool written = Data()->WriteEntryHeader(it->second, eh);
667+
668+
if (!written) {
669+
SetCorrupted(
670+
TStringBuilder() << "Cannot write entry header at "
671+
<< CurrentAllocation.ActualPos);
672+
return MakeBufferIsCorruptError();
673+
}
661674

662675
EntryMap.erase(it);
663676

664677
EraseFreeEntriesFromFront();
665678

679+
if (IsCorrupted()) {
680+
// EraseFreeEntriesFromFront() may set IsCorrupted flag
681+
return MakeBufferIsCorruptError();
682+
}
683+
666684
return {};
667685
}
668686

cloud/storage/core/libs/file_backed_containers/file_ring_buffer_ut.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,37 @@ Y_UNIT_TEST_SUITE(TFileRingBufferTest)
663663
UNIT_ASSERT_STRINGS_EQUAL(dump, s.Dump());
664664
}
665665

666+
FILE_RING_BUFFER_TEST(ShouldDetectCorruptionOnPopFront)
667+
{
668+
const auto f = TTempFileHandle();
669+
const ui32 len = 42;
670+
TFileRingBuffer rb(f.GetName(), len, 0, ver);
671+
672+
UNIT_ASSERT_VALUES_EQUAL(true, rb.PushBack("abc"));
673+
UNIT_ASSERT_VALUES_EQUAL(true, rb.PushBack("def"));
674+
675+
{
676+
// Corrupt the buffer
677+
TFileMapFileRingBufferAccessor accessor(
678+
f.GetName(),
679+
EFileRingBufferAccessorValidationMode::Normal,
680+
TMemoryMapCommon::EOpenModeFlag::oRdWr);
681+
682+
UNIT_ASSERT(!HasError(accessor.Map()));
683+
684+
UNIT_ASSERT_VALUES_EQUAL(
685+
EFileRingBufferAccessorValidationStatus::Success,
686+
accessor.ValidateAndInitialize());
687+
688+
auto eh = accessor.GetDataProcessor()->ReadEntryHeader(0);
689+
UNIT_ASSERT_VALUES_EQUAL(3, eh.DataSize);
690+
eh.DataSize = 1000;
691+
accessor.GetDataProcessor()->WriteEntryHeader(0, eh);
692+
}
693+
694+
UNIT_ASSERT(HasError(rb.PopFront()));
695+
}
696+
666697
FILE_RING_BUFFER_TEST(ShouldGetRawCapacity)
667698
{
668699
const auto f = TTempFileHandle();

0 commit comments

Comments
 (0)