Skip to content

Commit 2459781

Browse files
committed
delta: fix out-of-bounds read of delta
When computing the offset and length of the delta base, we repeatedly increment the `delta` pointer without checking whether we have advanced past its end already, which can thus result in an out-of-bounds read. Fix this by repeatedly checking whether we have reached the end. Add a test which would cause Valgrind to produce an error. Reported-by: Riccardo Schirone <rschiron@redhat.com> Test-provided-by: Riccardo Schirone <rschiron@redhat.com>
1 parent 7db2587 commit 2459781

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

src/delta.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -568,15 +568,17 @@ int git_delta_apply(
568568
/* cmd is a copy instruction; copy from the base. */
569569
size_t off = 0, len = 0;
570570

571-
if (cmd & 0x01) off = *delta++;
572-
if (cmd & 0x02) off |= *delta++ << 8UL;
573-
if (cmd & 0x04) off |= *delta++ << 16UL;
574-
if (cmd & 0x08) off |= ((unsigned) *delta++ << 24UL);
575-
576-
if (cmd & 0x10) len = *delta++;
577-
if (cmd & 0x20) len |= *delta++ << 8UL;
578-
if (cmd & 0x40) len |= *delta++ << 16UL;
571+
#define ADD_DELTA(o, shift) { if (delta < delta_end) (o) |= ((unsigned) *delta++ << shift); else goto fail; }
572+
if (cmd & 0x01) ADD_DELTA(off, 0UL);
573+
if (cmd & 0x02) ADD_DELTA(off, 8UL);
574+
if (cmd & 0x04) ADD_DELTA(off, 16UL);
575+
if (cmd & 0x08) ADD_DELTA(off, 24UL);
576+
577+
if (cmd & 0x10) ADD_DELTA(len, 0UL);
578+
if (cmd & 0x20) ADD_DELTA(len, 8UL);
579+
if (cmd & 0x40) ADD_DELTA(len, 16UL);
579580
if (!len) len = 0x10000;
581+
#undef ADD_DELTA
580582

581583
if (base_len < off + len || res_sz < len)
582584
goto fail;

tests/delta/apply.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,12 @@ void test_delta_apply__read_at_off(void)
1010

1111
cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta)));
1212
}
13+
14+
void test_delta_apply__read_after_limit(void)
15+
{
16+
unsigned char base[16] = { 0 }, delta[] = { 0x10, 0x70, 0xff };
17+
void *out;
18+
size_t outlen;
19+
20+
cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta)));
21+
}

0 commit comments

Comments
 (0)