Skip to content

Commit 19716b2

Browse files
derrickstoleegitster
authored andcommitted
cleanup: fix possible overflow errors in binary search
A common mistake when writing binary search is to allow possible integer overflow by using the simple average: mid = (min + max) / 2; Instead, use the overflow-safe version: mid = min + (max - min) / 2; This translation is safe since the operation occurs inside a loop conditioned on "min < max". The included changes were found using the following git grep: git grep '/ *2;' '*.c' Making this cleanup will prevent future review friction when a new binary search is contructed based on existing code. Signed-off-by: Derrick Stolee <[email protected]> Reviewed-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 217f276 commit 19716b2

File tree

12 files changed

+15
-15
lines changed

12 files changed

+15
-15
lines changed

builtin/index-pack.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ static int find_ofs_delta(const off_t offset, enum object_type type)
633633
int first = 0, last = nr_ofs_deltas;
634634

635635
while (first < last) {
636-
int next = (first + last) / 2;
636+
int next = first + (last - first) / 2;
637637
struct ofs_delta_entry *delta = &ofs_deltas[next];
638638
int cmp;
639639

@@ -687,7 +687,7 @@ static int find_ref_delta(const unsigned char *sha1, enum object_type type)
687687
int first = 0, last = nr_ref_deltas;
688688

689689
while (first < last) {
690-
int next = (first + last) / 2;
690+
int next = first + (last - first) / 2;
691691
struct ref_delta_entry *delta = &ref_deltas[next];
692692
int cmp;
693693

builtin/pack-objects.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,7 @@ static int done_pbase_path_pos(unsigned hash)
12771277
int lo = 0;
12781278
int hi = done_pbase_paths_num;
12791279
while (lo < hi) {
1280-
int mi = (hi + lo) / 2;
1280+
int mi = lo + (hi - lo) / 2;
12811281
if (done_pbase_paths[mi] == hash)
12821282
return mi;
12831283
if (done_pbase_paths[mi] < hash)

builtin/unpack-objects.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
394394
lo = 0;
395395
hi = nr;
396396
while (lo < hi) {
397-
mid = (lo + hi)/2;
397+
mid = lo + (hi - lo) / 2;
398398
if (base_offset < obj_list[mid].offset) {
399399
hi = mid;
400400
} else if (base_offset > obj_list[mid].offset) {

cache-tree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ static int subtree_pos(struct cache_tree *it, const char *path, int pathlen)
4949
lo = 0;
5050
hi = it->subtree_nr;
5151
while (lo < hi) {
52-
int mi = (lo + hi) / 2;
52+
int mi = lo + (hi - lo) / 2;
5353
struct cache_tree_sub *mdl = down[mi];
5454
int cmp = subtree_name_cmp(path, pathlen,
5555
mdl->name, mdl->namelen);

compat/regex/regex_internal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
613613
int low = 0, high = pstr->valid_len, mid;
614614
do
615615
{
616-
mid = (high + low) / 2;
616+
mid = low + (high - low) / 2;
617617
if (pstr->offsets[mid] > offset)
618618
high = mid;
619619
else if (pstr->offsets[mid] < offset)
@@ -1394,7 +1394,7 @@ re_node_set_contains (const re_node_set *set, int elem)
13941394
right = set->nelem - 1;
13951395
while (idx < right)
13961396
{
1397-
mid = (idx + right) / 2;
1397+
mid = idx + (right - idx) / 2;
13981398
if (set->elems[mid] < elem)
13991399
idx = mid + 1;
14001400
else

compat/regex/regexec.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4284,7 +4284,7 @@ search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
42844284
last = right = mctx->nbkref_ents;
42854285
for (left = 0; left < right;)
42864286
{
4287-
mid = (left + right) / 2;
4287+
mid = left + (right - left) / 2;
42884288
if (mctx->bkref_ents[mid].str_idx < str_idx)
42894289
left = mid + 1;
42904290
else

packfile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1743,7 +1743,7 @@ off_t find_pack_entry_one(const unsigned char *sha1,
17431743
sha1[0], sha1[1], sha1[2], lo, hi, p->num_objects);
17441744

17451745
while (lo < hi) {
1746-
unsigned mi = (lo + hi) / 2;
1746+
unsigned mi = lo + (hi - lo) / 2;
17471747
int cmp = hashcmp(index + mi * stride, sha1);
17481748

17491749
if (debug_lookup)

sha1-lookup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ static uint32_t take2(const unsigned char *sha1)
1010
* Conventional binary search loop looks like this:
1111
*
1212
* do {
13-
* int mi = (lo + hi) / 2;
13+
* int mi = lo + (hi - lo) / 2;
1414
* int cmp = "entry pointed at by mi" minus "target";
1515
* if (!cmp)
1616
* return (mi is the wanted one)
@@ -95,7 +95,7 @@ int sha1_pos(const unsigned char *sha1, void *table, size_t nr,
9595
hi = mi;
9696
else
9797
lo = mi + 1;
98-
mi = (hi + lo) / 2;
98+
mi = lo + (hi - lo) / 2;
9999
} while (lo < hi);
100100
return -lo-1;
101101
}

sha1_name.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ static void unique_in_pack(struct packed_git *p,
157157
num = p->num_objects;
158158
last = num;
159159
while (first < last) {
160-
uint32_t mid = (first + last) / 2;
160+
uint32_t mid = first + (last - first) / 2;
161161
const unsigned char *current;
162162
int cmp;
163163

string-list.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ static int get_entry_index(const struct string_list *list, const char *string,
1616
compare_strings_fn cmp = list->cmp ? list->cmp : strcmp;
1717

1818
while (left + 1 < right) {
19-
int middle = (left + right) / 2;
19+
int middle = left + (right - left) / 2;
2020
int compare = cmp(string, list->items[middle].string);
2121
if (compare < 0)
2222
right = middle;

utf8.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static int bisearch(ucs_char_t ucs, const struct interval *table, int max)
3232
if (ucs < table[0].first || ucs > table[max].last)
3333
return 0;
3434
while (max >= min) {
35-
mid = (min + max) / 2;
35+
mid = min + (max - min) / 2;
3636
if (ucs > table[mid].last)
3737
min = mid + 1;
3838
else if (ucs < table[mid].first)

xdiff/xpatience.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ static int binary_search(struct entry **sequence, int longest,
166166
int left = -1, right = longest;
167167

168168
while (left + 1 < right) {
169-
int middle = (left + right) / 2;
169+
int middle = left + (right - left) / 2;
170170
/* by construction, no two entries can be equal */
171171
if (sequence[middle]->line2 > entry->line2)
172172
right = middle;

0 commit comments

Comments
 (0)