Skip to content

Commit ad341eb

Browse files
authored
Merge pull request libgit2#5425 from lhchavez/fix-get-delta-base
pack: Improve error handling for get_delta_base()
2 parents 5a1ec7a + 4d4c8e0 commit ad341eb

File tree

3 files changed

+44
-26
lines changed

3 files changed

+44
-26
lines changed

src/indexer.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,11 @@ static int advance_delta_offset(git_indexer *idx, git_object_t type)
265265
if (type == GIT_OBJECT_REF_DELTA) {
266266
idx->off += GIT_OID_RAWSZ;
267267
} else {
268-
off64_t base_off = get_delta_base(idx->pack, &w, &idx->off, type, idx->entry_start);
268+
off64_t base_off;
269+
int error = get_delta_base(&base_off, idx->pack, &w, &idx->off, type, idx->entry_start);
269270
git_mwindow_close(&w);
270-
if (base_off < 0)
271-
return (int)base_off;
271+
if (error < 0)
272+
return error;
272273
}
273274

274275
return 0;

src/pack.c

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,12 @@ int git_packfile_resolve_header(
488488
size_t base_size;
489489
git_packfile_stream stream;
490490

491-
base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
491+
error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, offset);
492492
git_mwindow_close(&w_curs);
493+
494+
if (error < 0)
495+
return error;
496+
493497
if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0)
494498
return error;
495499
error = git_delta_read_header_fromstream(&base_size, size_p, &stream);
@@ -508,8 +512,12 @@ int git_packfile_resolve_header(
508512
return error;
509513
if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
510514
break;
511-
base_offset = get_delta_base(p, &w_curs, &curpos, type, base_offset);
515+
516+
error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, base_offset);
512517
git_mwindow_close(&w_curs);
518+
519+
if (error < 0)
520+
return error;
513521
}
514522
*type_p = type;
515523

@@ -583,17 +591,11 @@ static int pack_dependency_chain(git_dependency_chain *chain_out,
583591
if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
584592
break;
585593

586-
base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
594+
error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, obj_offset);
587595
git_mwindow_close(&w_curs);
588596

589-
if (base_offset == 0) {
590-
error = packfile_error("delta offset is zero");
591-
goto on_error;
592-
}
593-
if (base_offset < 0) { /* must actually be an error code */
594-
error = (int)base_offset;
597+
if (error < 0)
595598
goto on_error;
596-
}
597599

598600
/* we need to pass the pos *after* the delta-base bit */
599601
elem->offset = curpos;
@@ -878,18 +880,21 @@ static int packfile_unpack_compressed(
878880
* curpos is where the data starts, delta_obj_offset is the where the
879881
* header starts
880882
*/
881-
off64_t get_delta_base(
882-
struct git_pack_file *p,
883-
git_mwindow **w_curs,
884-
off64_t *curpos,
885-
git_object_t type,
886-
off64_t delta_obj_offset)
883+
int get_delta_base(
884+
off64_t *delta_base_out,
885+
struct git_pack_file *p,
886+
git_mwindow **w_curs,
887+
off64_t *curpos,
888+
git_object_t type,
889+
off64_t delta_obj_offset)
887890
{
888891
unsigned int left = 0;
889892
unsigned char *base_info;
890893
off64_t base_offset;
891894
git_oid unused;
892895

896+
assert(delta_base_out);
897+
893898
base_info = pack_window_open(p, w_curs, *curpos, &left);
894899
/* Assumption: the only reason this would fail is because the file is too small */
895900
if (base_info == NULL)
@@ -909,12 +914,12 @@ off64_t get_delta_base(
909914
return GIT_EBUFS;
910915
unsigned_base_offset += 1;
911916
if (!unsigned_base_offset || MSB(unsigned_base_offset, 7))
912-
return 0; /* overflow */
917+
return packfile_error("overflow");
913918
c = base_info[used++];
914919
unsigned_base_offset = (unsigned_base_offset << 7) + (c & 127);
915920
}
916921
if (unsigned_base_offset == 0 || (size_t)delta_obj_offset <= unsigned_base_offset)
917-
return 0; /* out of bound */
922+
return packfile_error("out of bounds");
918923
base_offset = delta_obj_offset - unsigned_base_offset;
919924
*curpos += used;
920925
} else if (type == GIT_OBJECT_REF_DELTA) {
@@ -925,8 +930,12 @@ off64_t get_delta_base(
925930

926931
git_oid_fromraw(&oid, base_info);
927932
if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) {
933+
if (entry->offset == 0)
934+
return packfile_error("delta offset is zero");
935+
928936
*curpos += 20;
929-
return entry->offset;
937+
*delta_base_out = entry->offset;
938+
return 0;
930939
} else {
931940
/* If we're building an index, don't try to find the pack
932941
* entry; we just haven't seen it yet. We'll make
@@ -941,9 +950,13 @@ off64_t get_delta_base(
941950
return packfile_error("base entry delta is not in the same pack");
942951
*curpos += 20;
943952
} else
944-
return 0;
953+
return packfile_error("unknown object type");
945954

946-
return base_offset;
955+
if (base_offset == 0)
956+
return packfile_error("delta offset is zero");
957+
958+
*delta_base_out = base_offset;
959+
return 0;
947960
}
948961

949962
/***********************************************************

src/pack.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,12 @@ int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p,
143143
ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t len);
144144
void git_packfile_stream_dispose(git_packfile_stream *obj);
145145

146-
off64_t get_delta_base(struct git_pack_file *p, git_mwindow **w_curs,
147-
off64_t *curpos, git_object_t type,
146+
int get_delta_base(
147+
off64_t *delta_base_out,
148+
struct git_pack_file *p,
149+
git_mwindow **w_curs,
150+
off64_t *curpos,
151+
git_object_t type,
148152
off64_t delta_obj_offset);
149153

150154
void git_packfile_close(struct git_pack_file *p, bool unlink_packfile);

0 commit comments

Comments
 (0)