Skip to content

Commit e467a90

Browse files
tgummerergitster
authored andcommitted
linear-assignment: fix potential out of bounds memory access
Currently the 'compute_assignment()' function may read memory out of bounds, even if used correctly. Namely this happens when we only have one column. In that case we try to calculate the initial minimum cost using '!j1' as column in the reduction transfer code. That in turn causes us to try and get the cost from column 1 in the cost matrix, which does not exist, and thus results in an out of bounds memory read. In the original paper [1], the example code initializes that minimum cost to "infinite". We could emulate something similar by setting the minimum cost to INT_MAX, which would result in the same minimum cost as the current algorithm, as we'd always go into the if condition at least once, except when we only have one column, and column_count thus equals 1. If column_count does equal 1, the condition in the loop would always be false, and we'd end up with a minimum of INT_MAX, which may lead to integer overflows later in the algorithm. For a column count of 1, we however do not even really need to go through the whole algorithm. A column count of 1 means that there's no possible assignments, and we can just zero out the column2row and row2column arrays, and return early from the function, while keeping the reduction transfer part of the function the same as it is currently. Another solution would be to just not call the 'compute_assignment()' function from the range diff code in this case, however it's better to make the compute_assignment function more robust, so future callers don't run into this potential problem. Note that the test only fails under valgrind on Linux, but the same command has been reported to segfault on Mac OS. [1]: Jonker, R., & Volgenant, A. (1987). A shortest augmenting path algorithm for dense and sparse linear assignment problems. Computing, 38(4), 325–340. Reported-by: ryenus <[email protected]> Helped-by: Derrick Stolee <[email protected]> Signed-off-by: Thomas Gummerer <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 72f47be commit e467a90

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

linear-assignment.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ void compute_assignment(int column_count, int row_count, int *cost,
1919
int *free_row, free_count = 0, saved_free_count, *pred, *col;
2020
int i, j, phase;
2121

22+
if (column_count < 2) {
23+
memset(column2row, 0, sizeof(int) * column_count);
24+
memset(row2column, 0, sizeof(int) * row_count);
25+
return;
26+
}
27+
2228
memset(column2row, -1, sizeof(int) * column_count);
2329
memset(row2column, -1, sizeof(int) * row_count);
2430
ALLOC_ARRAY(v, column_count);

t/t3206-range-diff.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,9 @@ test_expect_success 'changed message' '
142142
test_cmp expected actual
143143
'
144144

145+
test_expect_success 'no commits on one side' '
146+
git commit --amend -m "new message" &&
147+
git range-diff master HEAD@{1} HEAD
148+
'
149+
145150
test_done

0 commit comments

Comments
 (0)