Merge pull request #5425 from lhchavez/fix-get-delta-base pack: Improve error handling for get_delta_base()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
diff --git a/src/indexer.c b/src/indexer.c
index 68fdd85..8dc6c7a 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -265,10 +265,11 @@ static int advance_delta_offset(git_indexer *idx, git_object_t type)
if (type == GIT_OBJECT_REF_DELTA) {
idx->off += GIT_OID_RAWSZ;
} else {
- off64_t base_off = get_delta_base(idx->pack, &w, &idx->off, type, idx->entry_start);
+ off64_t base_off;
+ int error = get_delta_base(&base_off, idx->pack, &w, &idx->off, type, idx->entry_start);
git_mwindow_close(&w);
- if (base_off < 0)
- return (int)base_off;
+ if (error < 0)
+ return error;
}
return 0;
diff --git a/src/pack.c b/src/pack.c
index fcf64f5..4294a6e 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -488,8 +488,12 @@ int git_packfile_resolve_header(
size_t base_size;
git_packfile_stream stream;
- base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
+ error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, offset);
git_mwindow_close(&w_curs);
+
+ if (error < 0)
+ return error;
+
if ((error = git_packfile_stream_open(&stream, p, curpos)) < 0)
return error;
error = git_delta_read_header_fromstream(&base_size, size_p, &stream);
@@ -508,8 +512,12 @@ int git_packfile_resolve_header(
return error;
if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
break;
- base_offset = get_delta_base(p, &w_curs, &curpos, type, base_offset);
+
+ error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, base_offset);
git_mwindow_close(&w_curs);
+
+ if (error < 0)
+ return error;
}
*type_p = type;
@@ -583,17 +591,11 @@ static int pack_dependency_chain(git_dependency_chain *chain_out,
if (type != GIT_OBJECT_OFS_DELTA && type != GIT_OBJECT_REF_DELTA)
break;
- base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
+ error = get_delta_base(&base_offset, p, &w_curs, &curpos, type, obj_offset);
git_mwindow_close(&w_curs);
- if (base_offset == 0) {
- error = packfile_error("delta offset is zero");
- goto on_error;
- }
- if (base_offset < 0) { /* must actually be an error code */
- error = (int)base_offset;
+ if (error < 0)
goto on_error;
- }
/* we need to pass the pos *after* the delta-base bit */
elem->offset = curpos;
@@ -878,18 +880,21 @@ out:
* curpos is where the data starts, delta_obj_offset is the where the
* header starts
*/
-off64_t get_delta_base(
- struct git_pack_file *p,
- git_mwindow **w_curs,
- off64_t *curpos,
- git_object_t type,
- off64_t delta_obj_offset)
+int get_delta_base(
+ off64_t *delta_base_out,
+ struct git_pack_file *p,
+ git_mwindow **w_curs,
+ off64_t *curpos,
+ git_object_t type,
+ off64_t delta_obj_offset)
{
unsigned int left = 0;
unsigned char *base_info;
off64_t base_offset;
git_oid unused;
+ assert(delta_base_out);
+
base_info = pack_window_open(p, w_curs, *curpos, &left);
/* Assumption: the only reason this would fail is because the file is too small */
if (base_info == NULL)
@@ -909,12 +914,12 @@ off64_t get_delta_base(
return GIT_EBUFS;
unsigned_base_offset += 1;
if (!unsigned_base_offset || MSB(unsigned_base_offset, 7))
- return 0; /* overflow */
+ return packfile_error("overflow");
c = base_info[used++];
unsigned_base_offset = (unsigned_base_offset << 7) + (c & 127);
}
if (unsigned_base_offset == 0 || (size_t)delta_obj_offset <= unsigned_base_offset)
- return 0; /* out of bound */
+ return packfile_error("out of bounds");
base_offset = delta_obj_offset - unsigned_base_offset;
*curpos += used;
} else if (type == GIT_OBJECT_REF_DELTA) {
@@ -925,8 +930,12 @@ off64_t get_delta_base(
git_oid_fromraw(&oid, base_info);
if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) {
+ if (entry->offset == 0)
+ return packfile_error("delta offset is zero");
+
*curpos += 20;
- return entry->offset;
+ *delta_base_out = entry->offset;
+ return 0;
} else {
/* If we're building an index, don't try to find the pack
* entry; we just haven't seen it yet. We'll make
@@ -941,9 +950,13 @@ off64_t get_delta_base(
return packfile_error("base entry delta is not in the same pack");
*curpos += 20;
} else
- return 0;
+ return packfile_error("unknown object type");
- return base_offset;
+ if (base_offset == 0)
+ return packfile_error("delta offset is zero");
+
+ *delta_base_out = base_offset;
+ return 0;
}
/***********************************************************
diff --git a/src/pack.h b/src/pack.h
index a6a32ff..17ae722 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -143,8 +143,12 @@ int git_packfile_stream_open(git_packfile_stream *obj, struct git_pack_file *p,
ssize_t git_packfile_stream_read(git_packfile_stream *obj, void *buffer, size_t len);
void git_packfile_stream_dispose(git_packfile_stream *obj);
-off64_t get_delta_base(struct git_pack_file *p, git_mwindow **w_curs,
- off64_t *curpos, git_object_t type,
+int get_delta_base(
+ off64_t *delta_base_out,
+ struct git_pack_file *p,
+ git_mwindow **w_curs,
+ off64_t *curpos,
+ git_object_t type,
off64_t delta_obj_offset);
void git_packfile_close(struct git_pack_file *p, bool unlink_packfile);