@@ -83,16 +83,10 @@ static int commit_graph_compatible(struct repository *r)
83
83
struct commit_graph * load_commit_graph_one (const char * graph_file )
84
84
{
85
85
void * graph_map ;
86
- const unsigned char * data , * chunk_lookup ;
87
86
size_t graph_size ;
88
87
struct stat st ;
89
- uint32_t i ;
90
- struct commit_graph * graph ;
88
+ struct commit_graph * ret ;
91
89
int fd = git_open (graph_file );
92
- uint64_t last_chunk_offset ;
93
- uint32_t last_chunk_id ;
94
- uint32_t graph_signature ;
95
- unsigned char graph_version , hash_version ;
96
90
97
91
if (fd < 0 )
98
92
return NULL ;
@@ -107,27 +101,55 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
107
101
die (_ ("graph file %s is too small" ), graph_file );
108
102
}
109
103
graph_map = xmmap (NULL , graph_size , PROT_READ , MAP_PRIVATE , fd , 0 );
104
+ ret = parse_commit_graph (graph_map , fd , graph_size );
105
+
106
+ if (!ret ) {
107
+ munmap (graph_map , graph_size );
108
+ close (fd );
109
+ exit (1 );
110
+ }
111
+
112
+ return ret ;
113
+ }
114
+
115
+ struct commit_graph * parse_commit_graph (void * graph_map , int fd ,
116
+ size_t graph_size )
117
+ {
118
+ const unsigned char * data , * chunk_lookup ;
119
+ uint32_t i ;
120
+ struct commit_graph * graph ;
121
+ uint64_t last_chunk_offset ;
122
+ uint32_t last_chunk_id ;
123
+ uint32_t graph_signature ;
124
+ unsigned char graph_version , hash_version ;
125
+
126
+ if (!graph_map )
127
+ return NULL ;
128
+
129
+ if (graph_size < GRAPH_MIN_SIZE )
130
+ return NULL ;
131
+
110
132
data = (const unsigned char * )graph_map ;
111
133
112
134
graph_signature = get_be32 (data );
113
135
if (graph_signature != GRAPH_SIGNATURE ) {
114
136
error (_ ("graph signature %X does not match signature %X" ),
115
137
graph_signature , GRAPH_SIGNATURE );
116
- goto cleanup_fail ;
138
+ return NULL ;
117
139
}
118
140
119
141
graph_version = * (unsigned char * )(data + 4 );
120
142
if (graph_version != GRAPH_VERSION ) {
121
143
error (_ ("graph version %X does not match version %X" ),
122
144
graph_version , GRAPH_VERSION );
123
- goto cleanup_fail ;
145
+ return NULL ;
124
146
}
125
147
126
148
hash_version = * (unsigned char * )(data + 5 );
127
149
if (hash_version != oid_version ()) {
128
150
error (_ ("hash version %X does not match version %X" ),
129
151
hash_version , oid_version ());
130
- goto cleanup_fail ;
152
+ return NULL ;
131
153
}
132
154
133
155
graph = alloc_commit_graph ();
@@ -142,16 +164,27 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
142
164
last_chunk_offset = 8 ;
143
165
chunk_lookup = data + 8 ;
144
166
for (i = 0 ; i < graph -> num_chunks ; i ++ ) {
145
- uint32_t chunk_id = get_be32 ( chunk_lookup + 0 ) ;
146
- uint64_t chunk_offset = get_be64 ( chunk_lookup + 4 ) ;
167
+ uint32_t chunk_id ;
168
+ uint64_t chunk_offset ;
147
169
int chunk_repeated = 0 ;
148
170
171
+ if (data + graph_size - chunk_lookup <
172
+ GRAPH_CHUNKLOOKUP_WIDTH ) {
173
+ error (_ ("chunk lookup table entry missing; graph file may be incomplete" ));
174
+ free (graph );
175
+ return NULL ;
176
+ }
177
+
178
+ chunk_id = get_be32 (chunk_lookup + 0 );
179
+ chunk_offset = get_be64 (chunk_lookup + 4 );
180
+
149
181
chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH ;
150
182
151
183
if (chunk_offset > graph_size - the_hash_algo -> rawsz ) {
152
184
error (_ ("improper chunk offset %08x%08x" ), (uint32_t )(chunk_offset >> 32 ),
153
185
(uint32_t )chunk_offset );
154
- goto cleanup_fail ;
186
+ free (graph );
187
+ return NULL ;
155
188
}
156
189
157
190
switch (chunk_id ) {
@@ -186,7 +219,8 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
186
219
187
220
if (chunk_repeated ) {
188
221
error (_ ("chunk id %08x appears multiple times" ), chunk_id );
189
- goto cleanup_fail ;
222
+ free (graph );
223
+ return NULL ;
190
224
}
191
225
192
226
if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP )
@@ -200,11 +234,6 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
200
234
}
201
235
202
236
return graph ;
203
-
204
- cleanup_fail :
205
- munmap (graph_map , graph_size );
206
- close (fd );
207
- exit (1 );
208
237
}
209
238
210
239
static void prepare_commit_graph_one (struct repository * r , const char * obj_dir )
0 commit comments