diff options
author | Patrick Steinhardt <ps@pks.im> | 2016-05-02 16:49:59 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2016-05-02 17:45:24 +0200 |
commit | 153fde5b4349f12de4f152c26d3b298e58a69cd8 (patch) | |
tree | 50b647018b160908b90f7ec46c810459b9870253 | |
parent | 7f407710ef5d46b18ee68f7f6580e593ee486bb4 (diff) | |
download | libgit2-153fde5b4349f12de4f152c26d3b298e58a69cd8.tar.gz |
delta-apply: fix sign extension
We compute offsets by executing `off |= (*delta++ << 24)` for
multiple constants, where `off` is of type `size_t` and `delta`
is of type `unsigned char`. The usual arithmetic conversions (see
ISO C89 ยง3.2.1.5 "Usual arithmetic conversions") kick in here,
causing us to promote both operands to `int` and then extending
the result to an `unsigned long` when OR'ing it with `off`.
The integer promotion to `int` may result in wrong size
calculations for big values.
Fix the issue by making the constants `unsigned long`, causing both
operands to be promoted to `unsigned long`.
-rw-r--r-- | src/delta-apply.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/src/delta-apply.c b/src/delta-apply.c index 89745faa0..3830c1c77 100644 --- a/src/delta-apply.c +++ b/src/delta-apply.c @@ -90,13 +90,13 @@ int git__delta_apply( size_t off = 0, len = 0; if (cmd & 0x01) off = *delta++; - if (cmd & 0x02) off |= *delta++ << 8; - if (cmd & 0x04) off |= *delta++ << 16; - if (cmd & 0x08) off |= *delta++ << 24; + if (cmd & 0x02) off |= *delta++ << 8UL; + if (cmd & 0x04) off |= *delta++ << 16UL; + if (cmd & 0x08) off |= *delta++ << 24UL; if (cmd & 0x10) len = *delta++; - if (cmd & 0x20) len |= *delta++ << 8; - if (cmd & 0x40) len |= *delta++ << 16; + if (cmd & 0x20) len |= *delta++ << 8UL; + if (cmd & 0x40) len |= *delta++ << 16UL; if (!len) len = 0x10000; if (base_len < off + len || res_sz < len) |