From cf0396a563ce9ac81eb550d83d53fda519fa4a6f Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 2 May 2016 16:49:59 +0200 Subject: [PATCH] delta-apply: fix sign extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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`. --- src/delta-apply.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/delta-apply.c b/src/delta-apply.c index 6e86a81db..02ec7b75e 100644 --- a/src/delta-apply.c +++ b/src/delta-apply.c @@ -121,13 +121,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)