summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2018-06-29 09:11:02 +0200
committerPatrick Steinhardt <ps@pks.im>2018-06-29 09:30:02 +0200
commit24597812220325f1cb38f61e56b095ff38d1b1cb (patch)
treef1cbcd896bc749ad87c36089b840eb6d85eaacd6
parent7db258706ab4e09046255cdcbf27c5af8d29a551 (diff)
downloadlibgit2-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>
-rw-r--r--src/delta.c18
-rw-r--r--tests/delta/apply.c9
2 files changed, 19 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;
diff --git a/tests/delta/apply.c b/tests/delta/apply.c
index 24513e040..5bb95a283 100644
--- a/tests/delta/apply.c
+++ b/tests/delta/apply.c
@@ -10,3 +10,12 @@ void test_delta_apply__read_at_off(void)
cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta)));
}
+
+void test_delta_apply__read_after_limit(void)
+{
+ unsigned char base[16] = { 0 }, delta[] = { 0x10, 0x70, 0xff };
+ void *out;
+ size_t outlen;
+
+ cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta)));
+}