struct packed_git *p = IN_PACK(entry);
struct pack_window *w_curs = NULL;
uint32_t pos;
- off_t offset;
+ off_t offset, cur;
enum object_type type = oe_type(entry);
+ enum object_type in_pack_type;
off_t datalen;
unsigned char header[MAX_PACK_OBJECT_HEADER],
dheader[MAX_PACK_OBJECT_HEADER];
unsigned hdrlen;
const unsigned hashsz = the_hash_algo->rawsz;
- unsigned long entry_size = SIZE(entry);
+ size_t entry_size;
+
+ cur = entry->in_pack_offset;
+ in_pack_type = unpack_object_header(p, &w_curs, &cur, &entry_size);
+ if (in_pack_type < 0)
+ die(_("write_reuse_object: unable to parse object header of %s"),
+ oid_to_hex(&entry->idx.oid));
if (DELTA(entry))
type = (allow_ofs_delta && DELTA(entry)->idx.offset) ?
datalen -= entry->in_pack_header_size;
if (!pack_to_stdout && p->index_version == 1 &&
- check_pack_inflate(p, &w_curs, offset, datalen, entry_size)) {
+ check_pack_inflate(p, &w_curs, offset, datalen,
+ cast_size_t_to_ulong(entry_size))) {
error(_("corrupt packed object for %s"),
oid_to_hex(&entry->idx.oid));
unuse_pack(&w_curs);
{
off_t offset, next, cur;
enum object_type type;
- unsigned long size;
+ size_t size;
offset = pack_pos_to_offset(reuse_packfile, pos);
next = pack_pos_to_offset(reuse_packfile, pos + 1);
off_t ofs;
unsigned char *buf, c;
enum object_type type;
- unsigned long in_pack_size;
+ size_t in_pack_size;
buf = use_pack(p, &w_curs, entry->in_pack_offset, &avail);
default:
/* Not a delta hence we've already got all we need. */
oe_set_type(entry, entry->in_pack_type);
- SET_SIZE(entry, in_pack_size);
+ SET_SIZE(entry, cast_size_t_to_ulong(in_pack_size));
entry->in_pack_header_size = used;
if (oe_type(entry) < OBJ_COMMIT || oe_type(entry) > OBJ_BLOB)
goto give_up;
if (have_base &&
can_reuse_delta(&base_ref, entry, &base_entry)) {
oe_set_type(entry, entry->in_pack_type);
- SET_SIZE(entry, in_pack_size); /* delta size */
- SET_DELTA_SIZE(entry, in_pack_size);
+ SET_SIZE(entry, cast_size_t_to_ulong(in_pack_size)); /* delta size */
+ SET_DELTA_SIZE(entry, cast_size_t_to_ulong(in_pack_size));
if (base_entry) {
SET_DELTA(entry, base_entry);
struct pack_window *w_curs;
unsigned char *buf;
enum object_type type;
- unsigned long used, avail, size;
+ unsigned long used, avail;
+ size_t size;
if (e->type_ != OBJ_OFS_DELTA && e->type_ != OBJ_REF_DELTA) {
+ unsigned long sz;
packing_data_lock(&to_pack);
if (odb_read_object_info(the_repository->objects,
- &e->idx.oid, &size) < 0)
+ &e->idx.oid, &sz) < 0)
die(_("unable to get size of %s"),
oid_to_hex(&e->idx.oid));
packing_data_unlock(&to_pack);
- return size;
+ return sz;
}
p = oe_in_pack(pack, e);
unuse_pack(&w_curs);
packing_data_unlock(&to_pack);
- return size;
+ return cast_size_t_to_ulong(size);
}
static int try_delta(struct unpacked *trg, struct unpacked *src,
struct object_info oi = OBJECT_INFO_INIT;
struct odb_loose_read_stream *st;
unsigned long mapsize;
+ unsigned long size_ul;
void *mapped;
mapped = odb_source_loose_map_object(source, oid, &mapsize);
goto error;
}
- oi.sizep = &st->base.size;
+ /*
+ * object_info.sizep is unsigned long* (32-bit on Windows), but
+ * st->base.size is size_t (64-bit). Use temporary variable.
+ * Note: loose objects >4GB would still truncate here, but such
+ * large loose objects are uncommon (they'd normally be packed).
+ */
+ oi.sizep = &size_ul;
oi.typep = &st->base.type;
if (parse_loose_header(st->hdr, &oi) < 0 || st->base.type < 0)
goto error;
+ st->base.size = size_ul;
st->mapped = mapped;
st->mapsize = mapsize;
.base.read = read_istream_incore,
};
struct odb_incore_read_stream *st;
+ unsigned long size_ul;
int ret;
oi.typep = &stream.base.type;
- oi.sizep = &stream.base.size;
+ /*
+ * object_info.sizep is unsigned long* (32-bit on Windows), but
+ * stream.base.size is size_t (64-bit). We use a temporary variable
+ * because the types are incompatible. Note: this path still truncates
+ * for >4GB objects, but large objects should use pack streaming
+ * (packfile_store_read_object_stream) which handles size_t properly.
+ * This incore fallback is only used for small objects or when pack
+ * streaming is unavailable.
+ */
+ oi.sizep = &size_ul;
oi.contentp = (void **)&stream.buf;
ret = odb_read_object_info_extended(odb, oid, &oi,
OBJECT_INFO_DIE_IF_CORRUPT);
if (ret)
return ret;
+ stream.base.size = size_ul;
CALLOC_ARRAY(st, 1);
*st = stream;
odb_read_stream_close_fn close;
odb_read_stream_read_fn read;
enum object_type type;
- unsigned long size; /* inflated size of full object */
+ size_t size; /* inflated size of full object */
};
/*
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
enum object_type type;
- unsigned long len;
+ size_t len;
unpack_object_header_buffer((const unsigned char *)data,
(unsigned long)size, &type, &len);
{
off_t delta_obj_offset;
enum object_type type;
- unsigned long size;
+ size_t size;
if (pack_pos >= pack->p->num_objects)
return -1; /* not actually in the pack */
void *data;
struct object_id oid;
enum object_type type;
- unsigned long size;
+ size_t size;
off_t curpos;
int data_valid;
data = NULL;
data_valid = 0;
} else {
- data = unpack_entry(r, p, entries[i].offset, &type, &size);
+ unsigned long sz;
+ data = unpack_entry(r, p, entries[i].offset, &type, &sz);
+ size = sz;
data_valid = 1;
}
}
unsigned long unpack_object_header_buffer(const unsigned char *buf,
- unsigned long len, enum object_type *type, unsigned long *sizep)
+ unsigned long len, enum object_type *type, size_t *sizep)
{
unsigned shift;
size_t size, c;
size = c & 15;
shift = 4;
while (c & 0x80) {
- if (len <= used || (bitsizeof(long) - 7) < shift) {
+ /*
+ * Each continuation byte adds 7 bits. Ensure shift won't
+ * overflow size_t (use size_t not long for 64-bit on Windows).
+ */
+ if (len <= used || (bitsizeof(size_t) - 7) < shift) {
error("bad object header");
size = used = 0;
break;
size = st_add(size, st_left_shift(c & 0x7f, shift));
shift += 7;
}
- *sizep = cast_size_t_to_ulong(size);
+ *sizep = size;
return used;
}
int unpack_object_header(struct packed_git *p,
struct pack_window **w_curs,
off_t *curpos,
- unsigned long *sizep)
+ size_t *sizep)
{
unsigned char *base;
unsigned long left;
while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
off_t base_offset;
- unsigned long size;
+ size_t size;
/* Push the object we're going to leave behind */
if (poi_stack_nr >= poi_stack_alloc && poi_stack == small_poi_stack) {
poi_stack_alloc = alloc_nr(poi_stack_nr);
uint32_t *maybe_index_pos, struct object_info *oi)
{
struct pack_window *w_curs = NULL;
- unsigned long size;
+ size_t size;
off_t curpos = obj_offset;
enum object_type type = OBJ_NONE;
uint32_t pack_pos;
struct pack_window *w_curs = NULL;
off_t curpos = obj_offset;
void *data = NULL;
- unsigned long size;
+ size_t size;
enum object_type type;
struct unpack_entry_stack_ent small_delta_stack[UNPACK_ENTRY_STACK_PREALLOC];
struct unpack_entry_stack_ent *delta_stack = small_delta_stack;
(uintmax_t)curpos, p->pack_name);
data = NULL;
} else {
+ unsigned long sz;
data = patch_delta(base, base_size, delta_data,
- delta_size, &size);
+ delta_size, &sz);
+ size = sz;
/*
* We could not apply the delta; warn the user, but
struct odb_packed_read_stream *stream;
struct pack_window *window = NULL;
enum object_type in_pack_type;
- unsigned long size;
+ size_t size;
in_pack_type = unpack_object_header(pack, &window, &offset, &size);
unuse_pack(&window);
int is_pack_valid(struct packed_git *);
void *unpack_entry(struct repository *r, struct packed_git *, off_t, enum object_type *, unsigned long *);
-unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
+unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, size_t *sizep);
unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
-int unpack_object_header(struct packed_git *, struct pack_window **, off_t *, unsigned long *);
+int unpack_object_header(struct packed_git *, struct pack_window **, off_t *, size_t *);
off_t get_delta_base(struct packed_git *p, struct pack_window **w_curs,
off_t *curpos, enum object_type type,
off_t delta_obj_offset);