Skip to content

Commit f9e8854

Browse files
pks-tgitster
authored andcommitted
reftable/block: fix error handling when searching restart points
When doing the binary search over restart points in a block we need to decode the record keys. This decoding step can result in an error when the block is corrupted, which we indicate to the caller of the binary search by setting `args.error = 1`. But the only caller that exists mishandles this because it in fact performs the error check before calling `binsearch()`. Fix this bug by checking for errors at the right point in time. Furthermore, refactor `binsearch()` so that it aborts the search in case the callback function returns a negative value so that we don't needlessly continue to search the block. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 77307a6 commit f9e8854

File tree

3 files changed

+11
-8
lines changed

3 files changed

+11
-8
lines changed

reftable/basics.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@ size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args)
3939
*/
4040
while (hi - lo > 1) {
4141
size_t mid = lo + (hi - lo) / 2;
42+
int ret = f(mid, args);
43+
if (ret < 0)
44+
return sz;
4245

43-
if (f(mid, args))
46+
if (ret > 0)
4447
hi = mid;
4548
else
4649
lo = mid;

reftable/basics.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ uint32_t get_be24(uint8_t *in);
2222
void put_be16(uint8_t *out, uint16_t i);
2323

2424
/*
25-
* find smallest index i in [0, sz) at which f(i) is true, assuming
26-
* that f is ascending. Return sz if f(i) is false for all indices.
25+
* find smallest index i in [0, sz) at which `f(i) > 0`, assuming that f is
26+
* ascending. Return sz if `f(i) == 0` for all indices. The search is aborted
27+
* and `sz` is returned in case `f(i) < 0`.
2728
*
2829
* Contrary to bsearch(3), this returns something useful if the argument is not
2930
* found.

reftable/block.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,6 @@ int block_reader_seek(struct block_reader *br, struct block_iter *it,
387387
int err = 0;
388388
size_t i;
389389

390-
if (args.error) {
391-
err = REFTABLE_FORMAT_ERROR;
392-
goto done;
393-
}
394-
395390
/*
396391
* Perform a binary search over the block's restart points, which
397392
* avoids doing a linear scan over the whole block. Like this, we
@@ -405,6 +400,10 @@ int block_reader_seek(struct block_reader *br, struct block_iter *it,
405400
* too many record.
406401
*/
407402
i = binsearch(br->restart_count, &restart_needle_less, &args);
403+
if (args.error) {
404+
err = REFTABLE_FORMAT_ERROR;
405+
goto done;
406+
}
408407

409408
/*
410409
* Now there are multiple cases:

0 commit comments

Comments
 (0)