diff options
author | Patrick Steinhardt <ps@pks.im> | 2018-06-29 09:11:02 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2018-06-29 09:30:02 +0200 |
commit | 24597812220325f1cb38f61e56b095ff38d1b1cb (patch) | |
tree | f1cbcd896bc749ad87c36089b840eb6d85eaacd6 /src | |
parent | 7db258706ab4e09046255cdcbf27c5af8d29a551 (diff) | |
download | libgit2-24597812220325f1cb38f61e56b095ff38d1b1cb.tar.gz |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/delta.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/src/delta.c b/src/delta.c index 8d9e6146e..8676e7a8f 100644 --- a/src/delta.c +++ b/src/delta.c @@ -568,15 +568,17 @@ int git_delta_apply( /* cmd is a copy instruction; copy from the base. */ size_t off = 0, len = 0; - if (cmd & 0x01) off = *delta++; - if (cmd & 0x02) off |= *delta++ << 8UL; - if (cmd & 0x04) off |= *delta++ << 16UL; - if (cmd & 0x08) off |= ((unsigned) *delta++ << 24UL); - - if (cmd & 0x10) len = *delta++; - if (cmd & 0x20) len |= *delta++ << 8UL; - if (cmd & 0x40) len |= *delta++ << 16UL; +#define ADD_DELTA(o, shift) { if (delta < delta_end) (o) |= ((unsigned) *delta++ << shift); else goto fail; } + if (cmd & 0x01) ADD_DELTA(off, 0UL); + if (cmd & 0x02) ADD_DELTA(off, 8UL); + if (cmd & 0x04) ADD_DELTA(off, 16UL); + if (cmd & 0x08) ADD_DELTA(off, 24UL); + + if (cmd & 0x10) ADD_DELTA(len, 0UL); + if (cmd & 0x20) ADD_DELTA(len, 8UL); + if (cmd & 0x40) ADD_DELTA(len, 16UL); if (!len) len = 0x10000; +#undef ADD_DELTA if (base_len < off + len || res_sz < len) goto fail; |