Skip to content

Commit c048618

Browse files
committed
blame_git: detect memory allocation errors
The code in "blame_git.c" was mostly imported from git.git with only minor changes. One of these changes was to use our own allocators instead of git's `xmalloc`, but there's a subtle difference: `xmalloc` would abort the program if unable to allocate any memory, bit `git__malloc` doesn't. As we didn't check for memory allocation errors in some places, we might inadvertently dereference a `NULL` pointer in out-of-memory situations. Convert multiple functions to return proper error codes and add calls to `GIT_ERROR_CHECK_ALLOC` to fix this.
1 parent 0f40e68 commit c048618

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

src/blame_git.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static void dup_entry(git_blame__entry *dst, git_blame__entry *src)
219219
* split_overlap() divided an existing blame e into up to three parts in split.
220220
* Adjust the linked list of blames in the scoreboard to reflect the split.
221221
*/
222-
static void split_blame(git_blame *blame, git_blame__entry *split, git_blame__entry *e)
222+
static int split_blame(git_blame *blame, git_blame__entry *split, git_blame__entry *e)
223223
{
224224
git_blame__entry *new_entry;
225225

@@ -229,11 +229,13 @@ static void split_blame(git_blame *blame, git_blame__entry *split, git_blame__en
229229

230230
/* The last part -- me */
231231
new_entry = git__malloc(sizeof(*new_entry));
232+
GIT_ERROR_CHECK_ALLOC(new_entry);
232233
memcpy(new_entry, &(split[2]), sizeof(git_blame__entry));
233234
add_blame_entry(blame, new_entry);
234235

235236
/* ... and the middle part -- parent */
236237
new_entry = git__malloc(sizeof(*new_entry));
238+
GIT_ERROR_CHECK_ALLOC(new_entry);
237239
memcpy(new_entry, &(split[1]), sizeof(git_blame__entry));
238240
add_blame_entry(blame, new_entry);
239241
} else if (!split[0].suspect && !split[2].suspect) {
@@ -246,15 +248,19 @@ static void split_blame(git_blame *blame, git_blame__entry *split, git_blame__en
246248
/* me and then parent */
247249
dup_entry(e, &split[0]);
248250
new_entry = git__malloc(sizeof(*new_entry));
251+
GIT_ERROR_CHECK_ALLOC(new_entry);
249252
memcpy(new_entry, &(split[1]), sizeof(git_blame__entry));
250253
add_blame_entry(blame, new_entry);
251254
} else {
252255
/* parent and then me */
253256
dup_entry(e, &split[1]);
254257
new_entry = git__malloc(sizeof(*new_entry));
258+
GIT_ERROR_CHECK_ALLOC(new_entry);
255259
memcpy(new_entry, &(split[2]), sizeof(git_blame__entry));
256260
add_blame_entry(blame, new_entry);
257261
}
262+
263+
return 0;
258264
}
259265

260266
/*
@@ -272,7 +278,7 @@ static void decref_split(git_blame__entry *split)
272278
* Helper for blame_chunk(). blame_entry e is known to overlap with the patch
273279
* hunk; split it and pass blame to the parent.
274280
*/
275-
static void blame_overlap(
281+
static int blame_overlap(
276282
git_blame *blame,
277283
git_blame__entry *e,
278284
size_t tlno,
@@ -284,16 +290,19 @@ static void blame_overlap(
284290

285291
split_overlap(split, e, tlno, plno, same, parent);
286292
if (split[1].suspect)
287-
split_blame(blame, split, e);
293+
if (split_blame(blame, split, e) < 0)
294+
return -1;
288295
decref_split(split);
296+
297+
return 0;
289298
}
290299

291300
/*
292301
* Process one hunk from the patch between the current suspect for blame_entry
293302
* e and its parent. Find and split the overlap, and pass blame to the
294303
* overlapping part to the parent.
295304
*/
296-
static void blame_chunk(
305+
static int blame_chunk(
297306
git_blame *blame,
298307
size_t tlno,
299308
size_t plno,
@@ -309,9 +318,12 @@ static void blame_chunk(
309318
if (same <= e->s_lno)
310319
continue;
311320
if (tlno < e->s_lno + e->num_lines) {
312-
blame_overlap(blame, e, tlno, plno, same, parent);
321+
if (blame_overlap(blame, e, tlno, plno, same, parent) < 0)
322+
return -1;
313323
}
314324
}
325+
326+
return 0;
315327
}
316328

317329
static int my_emit(
@@ -321,7 +333,8 @@ static int my_emit(
321333
{
322334
blame_chunk_cb_data *d = (blame_chunk_cb_data *)cb_data;
323335

324-
blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent);
336+
if (blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent) < 0)
337+
return -1;
325338
d->plno = start_a + count_a;
326339
d->tlno = start_b + count_b;
327340

@@ -400,7 +413,8 @@ static int pass_blame_to_parent(
400413
return -1;
401414

402415
/* The reset (i.e. anything after tlno) are the same as the parent */
403-
blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent);
416+
if (blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent) < 0)
417+
return -1;
404418

405419
return 0;
406420
}

0 commit comments

Comments
 (0)