Skip to content

Commit 15e4573

Browse files
authored
Check iter index access slice bounds (#18213) (#18267)
2 parents 4543be8 + 7d9bd21 commit 15e4573

File tree

5 files changed

+242
-45
lines changed

5 files changed

+242
-45
lines changed

ydb/core/tablet_flat/flat_fwd_cache.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "flat_fwd_page.h"
77
#include "flat_table_part.h"
88
#include "flat_part_slice.h"
9+
#include <ydb/library/yverify_stream/yverify_stream.h>
910

1011
namespace NKikimr {
1112
namespace NTable {
@@ -281,6 +282,7 @@ namespace NFwd {
281282
TDeque<TPageEx> Pages;
282283
ui32 PagesBeginOffset = 0, PagesPendingOffset = 0;
283284
TDeque<TNodeState> Queue;
285+
TPageId BeginPageId = Max<TPageId>(), EndPageId = 0;
284286
};
285287

286288
public:
@@ -302,6 +304,8 @@ namespace NFwd {
302304
auto& meta = Part->IndexPages.GetBTree(groupId);
303305
Levels.resize(meta.LevelCount + 1);
304306
Levels[0].Queue.push_back({meta.GetPageId(), meta.GetDataSize()});
307+
Levels[0].BeginPageId = meta.GetPageId();
308+
Levels[0].EndPageId = meta.GetPageId() + 1;
305309
if (meta.LevelCount) {
306310
IndexPageLocator.Add(meta.GetPageId(), GroupId, 0);
307311
}
@@ -325,6 +329,9 @@ namespace NFwd {
325329
return {page, false, true};
326330
}
327331

332+
Y_VERIFY_S(level.BeginPageId <= pageId && pageId < level.EndPageId, "Requested page " << pageId << " is out of loaded slice "
333+
<< BeginRowId << " " << EndRowId << " " << level.BeginPageId << " " << level.EndPageId << " with index " << Part->IndexPages.GetBTree(GroupId).ToString());
334+
328335
DropPagesBefore(level, pageId);
329336
ShrinkPages(level);
330337

@@ -436,8 +443,13 @@ namespace NFwd {
436443
if (child.GetRowCount() <= BeginRowId) {
437444
continue;
438445
}
439-
Y_ABORT_UNLESS(!Levels[levelId + 1].Queue || Levels[levelId + 1].Queue.back().PageId < child.GetPageId());
440-
Levels[levelId + 1].Queue.push_back({child.GetPageId(), child.GetDataSize()});
446+
auto& nextLevel = Levels[levelId + 1];
447+
Y_ABORT_UNLESS(!nextLevel.Queue || nextLevel.Queue.back().PageId < child.GetPageId());
448+
nextLevel.Queue.push_back({child.GetPageId(), child.GetDataSize()});
449+
if (nextLevel.BeginPageId == Max<TPageId>()) {
450+
nextLevel.BeginPageId = child.GetPageId();
451+
}
452+
nextLevel.EndPageId = child.GetPageId() + 1;
441453
if (child.GetRowCount() >= EndRowId) {
442454
break;
443455
}

ydb/core/tablet_flat/flat_page_btree_index.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ namespace NKikimr::NTable::NPage {
8989
TRowId RowCount_;
9090
ui64 DataSize_;
9191

92+
auto operator<=>(const TShortChild&) const = default;
93+
9294
inline TPageId GetPageId() const noexcept {
9395
return PageId_;
9496
}
@@ -101,7 +103,9 @@ namespace NKikimr::NTable::NPage {
101103
return DataSize_;
102104
}
103105

104-
auto operator<=>(const TShortChild&) const = default;
106+
TString ToString() const {
107+
return TStringBuilder() << "PageId: " << GetPageId() << " RowCount: " << GetRowCount() << " DataSize: " << GetDataSize();
108+
}
105109
} Y_PACKED;
106110

107111
static_assert(sizeof(TShortChild) == 20, "Invalid TBtreeIndexNode TShortChild size");

ydb/core/tablet_flat/flat_part_iter.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ namespace NTable {
186186
return EReady::Data;
187187
}
188188

189+
if (Page.BaseRow() + Page->Count >= EndRowId) {
190+
// Row is outside of bounds
191+
return Exhausted();
192+
}
193+
189194
if (seek != ESeek::Exact) {
190195
// The row we seek is on the next page
191196

ydb/core/tablet_flat/test/libs/table/test_envs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ namespace NTest {
304304
for (ui32 room : xrange(partStore->Store->GetRoomCount())) {
305305
if (room < partStore->Store->GetGroupCount()) {
306306
NPage::TGroupId groupId(room);
307-
partGroupQueues.push_back(Settle(partStore, room, NFwd::CreateCache(part, PartIndexPageLocator[part], groupId)));
307+
partGroupQueues.push_back(Settle(partStore, room, NFwd::CreateCache(part, PartIndexPageLocator[part], groupId, partStore->Slices)));
308308
} else if (room == partStore->Store->GetOuterRoom()) {
309309
partGroupQueues.push_back(Settle(partStore, room, MakeOuter(partStore)));
310310
} else if (room == partStore->Store->GetExternRoom()) {

0 commit comments

Comments
 (0)