diff --git a/patch-delta.c b/patch-delta.c index b937afd2c9..283fb4b759 100644 --- a/patch-delta.c +++ b/patch-delta.c @@ -51,13 +51,13 @@ void *patch_delta(const void *src_buf, unsigned long src_size, if (unsigned_add_overflows(cp_off, cp_size) || cp_off + cp_size > src_size || cp_size > size) - break; + goto bad_length; memcpy(out, (char *) src_buf + cp_off, cp_size); out += cp_size; size -= cp_size; } else if (cmd) { if (cmd > size || cmd > top - data) - break; + goto bad_length; memcpy(out, data, cmd); out += cmd; data += cmd; @@ -75,6 +75,7 @@ void *patch_delta(const void *src_buf, unsigned long src_size, /* sanity check */ if (data != top || size != 0) { + bad_length: error("delta replay has gone wild"); bad: free(dst_buf); diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh index 7114c31ade..41dc947d3f 100755 --- a/t/t5303-pack-corruption-resilience.sh +++ b/t/t5303-pack-corruption-resilience.sh @@ -370,4 +370,34 @@ test_expect_failure \ echo base >base && test_must_fail test-tool delta -p base truncated_copy_delta /dev/null' +# \0 - empty base +# \1 - one byte in result +# \1 - one literal byte (X) +# \1 - trailing garbage command +test_expect_success \ + 'apply delta with trailing garbage literal' \ + 'printf "\0\1\1X\1" > tail_garbage_literal && + test_must_fail test-tool delta -p /dev/null tail_garbage_literal /dev/null' + +# \5 - five bytes in base +# \1 - one byte in result +# \1 - one literal byte (X) +# \221 - copy, one byte offset, one byte size +# \0 - copy from offset 0 +# \1 - copy 1 byte +test_expect_success \ + 'apply delta with trailing garbage copy' \ + 'printf "\5\1\1X\221\0\1" > tail_garbage_copy && + echo base >base && + test_must_fail test-tool delta -p /dev/null tail_garbage_copy /dev/null' + +# \0 - empty base +# \1 - one byte in result +# \1 - one literal byte (X) +# \0 - bogus opcode +test_expect_success \ + 'apply delta with trailing garbage opcode' \ + 'printf "\0\1\1X\0" > tail_garbage_opcode && + test_must_fail test-tool delta -p /dev/null tail_garbage_opcode /dev/null' + test_done