Skip to content

Commit 20e92c1

Browse files
committed
FT-591 fix valgrind uninitialized value error in block allocator test caused by reading past the end of a the blockpair array
1 parent cf3dae3 commit 20e92c1

File tree

1 file changed

+33
-10
lines changed

1 file changed

+33
-10
lines changed

ft/serialize/block_allocator_strategy.cc

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,43 @@ static uint64_t _roundup_to_power_of_two(uint64_t value) {
111111
static struct block_allocator::blockpair *
112112
_first_fit(struct block_allocator::blockpair *blocks_array,
113113
uint64_t n_blocks, uint64_t size, uint64_t alignment,
114-
bool forward, uint64_t max_padding) {
114+
uint64_t max_padding) {
115115
if (n_blocks == 1) {
116116
// won't enter loop, can't underflow the direction < 0 case
117117
return nullptr;
118118
}
119119

120-
struct block_allocator::blockpair *bp = forward ? &blocks_array[0] : &blocks_array[-1];
120+
struct block_allocator::blockpair *bp = &blocks_array[0];
121121
for (uint64_t n_spaces_to_check = n_blocks - 1; n_spaces_to_check > 0;
122-
n_spaces_to_check--, forward ? bp++ : bp--) {
122+
n_spaces_to_check--, bp++) {
123123
// Consider the space after bp
124124
uint64_t padded_alignment = max_padding != 0 ? _align(max_padding, alignment) : alignment;
125125
uint64_t possible_offset = _align(bp->offset + bp->size, padded_alignment);
126-
if (possible_offset + size <= bp[1].offset) {
127-
invariant((forward ? bp - blocks_array : blocks_array - bp) < (int64_t) n_blocks);
126+
if (possible_offset + size <= bp[1].offset) { // bp[1] is always valid since bp < &blocks_array[n_blocks-1]
127+
invariant(bp - blocks_array < (int64_t) n_blocks);
128+
return bp;
129+
}
130+
}
131+
return nullptr;
132+
}
133+
134+
static struct block_allocator::blockpair *
135+
_first_fit_bw(struct block_allocator::blockpair *blocks_array,
136+
uint64_t n_blocks, uint64_t size, uint64_t alignment,
137+
uint64_t max_padding, struct block_allocator::blockpair *blocks_array_limit) {
138+
if (n_blocks == 1) {
139+
// won't enter loop, can't underflow the direction < 0 case
140+
return nullptr;
141+
}
142+
143+
struct block_allocator::blockpair *bp = &blocks_array[-1];
144+
for (uint64_t n_spaces_to_check = n_blocks - 1; n_spaces_to_check > 0;
145+
n_spaces_to_check--, bp--) {
146+
// Consider the space after bp
147+
uint64_t padded_alignment = max_padding != 0 ? _align(max_padding, alignment) : alignment;
148+
uint64_t possible_offset = _align(bp->offset + bp->size, padded_alignment);
149+
if (&bp[1] < blocks_array_limit && possible_offset + size <= bp[1].offset) {
150+
invariant(blocks_array - bp < (int64_t) n_blocks);
128151
return bp;
129152
}
130153
}
@@ -134,7 +157,7 @@ _first_fit(struct block_allocator::blockpair *blocks_array,
134157
struct block_allocator::blockpair *
135158
block_allocator_strategy::first_fit(struct block_allocator::blockpair *blocks_array,
136159
uint64_t n_blocks, uint64_t size, uint64_t alignment) {
137-
return _first_fit(blocks_array, n_blocks, size, alignment, true, 0);
160+
return _first_fit(blocks_array, n_blocks, size, alignment, 0);
138161
}
139162

140163
// Best fit block allocation
@@ -188,7 +211,7 @@ static void determine_padded_fit_alignment_from_env(void) {
188211
struct block_allocator::blockpair *
189212
block_allocator_strategy::padded_fit(struct block_allocator::blockpair *blocks_array,
190213
uint64_t n_blocks, uint64_t size, uint64_t alignment) {
191-
return _first_fit(blocks_array, n_blocks, size, alignment, true, padded_fit_alignment);
214+
return _first_fit(blocks_array, n_blocks, size, alignment, padded_fit_alignment);
192215
}
193216

194217
static double hot_zone_threshold = 0.85;
@@ -231,21 +254,21 @@ block_allocator_strategy::heat_zone(struct block_allocator::blockpair *blocks_ar
231254

232255
if (blocks_in_zone > 0) {
233256
// Find the first fit in the hot zone, going forward.
234-
bp = _first_fit(boundary_bp, blocks_in_zone, size, alignment, true, 0);
257+
bp = _first_fit(boundary_bp, blocks_in_zone, size, alignment, 0);
235258
if (bp != nullptr) {
236259
return bp;
237260
}
238261
}
239262
if (blocks_outside_zone > 0) {
240263
// Find the first fit in the cold zone, going backwards.
241-
bp = _first_fit(boundary_bp, blocks_outside_zone, size, alignment, false, 0);
264+
bp = _first_fit_bw(boundary_bp, blocks_outside_zone, size, alignment, 0, &blocks_array[n_blocks]);
242265
if (bp != nullptr) {
243266
return bp;
244267
}
245268
}
246269
} else {
247270
// Cold allocations are simply first-fit from the beginning.
248-
return _first_fit(blocks_array, n_blocks, size, alignment, true, 0);
271+
return _first_fit(blocks_array, n_blocks, size, alignment, 0);
249272
}
250273
return nullptr;
251274
}

0 commit comments

Comments
 (0)