* This must be called twice on the delta data buffer, first to get the
* expected source buffer size, and again to get the target buffer size.
*/
-static inline unsigned long get_delta_hdr_size(const unsigned char **datap,
- const unsigned char *top)
+/*
+ * Size_t variant that doesn't truncate - use for >4GB objects on Windows.
+ */
+static inline size_t get_delta_hdr_size_sz(const unsigned char **datap,
+ const unsigned char *top)
{
const unsigned char *data = *datap;
size_t cmd, size = 0;
i += 7;
} while (cmd & 0x80 && data < top);
*datap = data;
+ return size;
+}
+
+static inline unsigned long get_delta_hdr_size(const unsigned char **datap,
+ const unsigned char *top)
+{
+ size_t size = get_delta_hdr_size_sz(datap, top);
return cast_size_t_to_ulong(size);
}
return used;
}
-unsigned long get_size_from_delta(struct packed_git *p,
- struct pack_window **w_curs,
- off_t curpos)
+/*
+ * Size_t variant for >4GB delta results on Windows.
+ */
+static size_t get_size_from_delta_sz(struct packed_git *p,
+ struct pack_window **w_curs,
+ off_t curpos)
{
const unsigned char *data;
unsigned char delta_head[20], *in;
data = delta_head;
/* ignore base size */
- get_delta_hdr_size(&data, delta_head+sizeof(delta_head));
+ get_delta_hdr_size_sz(&data, delta_head+sizeof(delta_head));
/* Read the result size */
- return get_delta_hdr_size(&data, delta_head+sizeof(delta_head));
+ return get_delta_hdr_size_sz(&data, delta_head+sizeof(delta_head));
+}
+
+unsigned long get_size_from_delta(struct packed_git *p,
+ struct pack_window **w_curs,
+ off_t curpos)
+{
+ size_t size = get_size_from_delta_sz(p, w_curs, curpos);
+ return cast_size_t_to_ulong(size);
}
int unpack_object_header(struct packed_git *p,
ret = -1;
goto out;
}
- *oi->sizep = get_size_from_delta(p, &w_curs, tmp_pos);
- if (*oi->sizep == 0) {
+ /*
+ * Use size_t variant to avoid die() on >4GB deltas.
+ * oi->sizep is unsigned long, so truncation may occur,
+ * but streaming code uses its own size_t tracking.
+ */
+ size = get_size_from_delta_sz(p, &w_curs, tmp_pos);
+ if (size == 0) {
ret = -1;
goto out;
}
- } else {
- *oi->sizep = size;
}
+ *oi->sizep = (unsigned long)size;
}
if (oi->disk_sizep || (oi->mtimep && p->is_cruft)) {