diff --git a/src/libgit2/delta.c b/src/libgit2/delta.c index 2d2c5fa85..1fd2278c8 100644 --- a/src/libgit2/delta.c +++ b/src/libgit2/delta.c @@ -477,8 +477,12 @@ static int hdr_sz( return -1; } + if (shift >= (sizeof(size_t) * 8)) { + git_error_set(GIT_ERROR_INVALID, "delta header overflow"); + return -1; + } c = *d++; - r |= (c & 0x7f) << shift; + r |= ((size_t)(c & 0x7f)) << shift; shift += 7; } while (c & 0x80); *delta = d; diff --git a/tests/libgit2/delta/shift_overflow.c b/tests/libgit2/delta/shift_overflow.c new file mode 100644 index 000000000..f3a6373bf --- /dev/null +++ b/tests/libgit2/delta/shift_overflow.c @@ -0,0 +1,16 @@ +#include "clar_libgit2.h" +#include "delta.h" + +void test_delta_shift_overflow__hdr_sz_shift_limit(void) +{ + unsigned char base[16] = { 0 }; + unsigned char delta[] = { + 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, + 0x80, 0x01 + }; + void *out; + size_t outlen; + + cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta))); +}