@@ -134,33 +134,6 @@ static void clear_packed_ref_cache(struct packed_ref_store *refs)
134134 }
135135}
136136
137- /* The length of a peeled reference line in packed-refs, including EOL: */
138- #define PEELED_LINE_LENGTH 42
139-
140- /*
141- * Parse one line from a packed-refs file. Write the SHA1 to sha1.
142- * Return a pointer to the refname within the line (null-terminated),
143- * or NULL if there was a problem.
144- */
145- static const char * parse_ref_line (struct strbuf * line , struct object_id * oid )
146- {
147- const char * ref ;
148-
149- if (parse_oid_hex (line -> buf , oid , & ref ) < 0 )
150- return NULL ;
151- if (!isspace (* ref ++ ))
152- return NULL ;
153-
154- if (isspace (* ref ))
155- return NULL ;
156-
157- if (line -> buf [line -> len - 1 ] != '\n' )
158- return NULL ;
159- line -> buf [-- line -> len ] = 0 ;
160-
161- return ref ;
162- }
163-
164137static NORETURN void die_unterminated_line (const char * path ,
165138 const char * p , size_t len )
166139{
@@ -221,8 +194,7 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
221194 size_t size ;
222195 char * buf ;
223196 const char * pos , * eol , * eof ;
224- struct ref_entry * last = NULL ;
225- struct strbuf line = STRBUF_INIT ;
197+ struct strbuf tmp = STRBUF_INIT ;
226198 enum { PEELED_NONE , PEELED_TAGS , PEELED_FULLY } peeled = PEELED_NONE ;
227199 struct ref_dir * dir ;
228200
@@ -264,9 +236,9 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
264236 if (!eol )
265237 die_unterminated_line (refs -> path , pos , eof - pos );
266238
267- strbuf_add (& line , pos , eol - pos );
239+ strbuf_add (& tmp , pos , eol - pos );
268240
269- if (!skip_prefix (line .buf , "# pack-refs with:" , (const char * * )& p ))
241+ if (!skip_prefix (tmp .buf , "# pack-refs with:" , (const char * * )& p ))
270242 die_invalid_line (refs -> path , pos , eof - pos );
271243
272244 string_list_split_in_place (& traits , p , ' ' , -1 );
@@ -281,61 +253,68 @@ static struct packed_ref_cache *read_packed_refs(struct packed_ref_store *refs)
281253 pos = eol + 1 ;
282254
283255 string_list_clear (& traits , 0 );
284- strbuf_reset (& line );
256+ strbuf_reset (& tmp );
285257 }
286258
287259 dir = get_ref_dir (packed_refs -> cache -> root );
288260 while (pos < eof ) {
261+ const char * p = pos ;
289262 struct object_id oid ;
290263 const char * refname ;
264+ int flag = REF_ISPACKED ;
265+ struct ref_entry * entry = NULL ;
291266
292- eol = memchr (pos , '\n' , eof - pos );
267+ if (eof - pos < GIT_SHA1_HEXSZ + 2 ||
268+ parse_oid_hex (p , & oid , & p ) ||
269+ !isspace (* p ++ ))
270+ die_invalid_line (refs -> path , pos , eof - pos );
271+
272+ eol = memchr (p , '\n' , eof - p );
293273 if (!eol )
294274 die_unterminated_line (refs -> path , pos , eof - pos );
295275
296- strbuf_add (& line , pos , eol + 1 - pos );
276+ strbuf_add (& tmp , p , eol - p );
277+ refname = tmp .buf ;
278+
279+ if (check_refname_format (refname , REFNAME_ALLOW_ONELEVEL )) {
280+ if (!refname_is_safe (refname ))
281+ die ("packed refname is dangerous: %s" , refname );
282+ oidclr (& oid );
283+ flag |= REF_BAD_NAME | REF_ISBROKEN ;
284+ }
285+ if (peeled == PEELED_FULLY ||
286+ (peeled == PEELED_TAGS && starts_with (refname , "refs/tags/" )))
287+ flag |= REF_KNOWS_PEELED ;
288+ entry = create_ref_entry (refname , & oid , flag );
289+ add_ref_entry (dir , entry );
297290
298- refname = parse_ref_line (& line , & oid );
299- if (refname ) {
300- int flag = REF_ISPACKED ;
291+ pos = eol + 1 ;
292+
293+ if (pos < eof && * pos == '^' ) {
294+ p = pos + 1 ;
295+ if (eof - p < GIT_SHA1_HEXSZ + 1 ||
296+ parse_oid_hex (p , & entry -> u .value .peeled , & p ) ||
297+ * p ++ != '\n' )
298+ die_invalid_line (refs -> path , pos , eof - pos );
301299
302- if (check_refname_format (refname , REFNAME_ALLOW_ONELEVEL )) {
303- if (!refname_is_safe (refname ))
304- die ("packed refname is dangerous: %s" , refname );
305- oidclr (& oid );
306- flag |= REF_BAD_NAME | REF_ISBROKEN ;
307- }
308- last = create_ref_entry (refname , & oid , flag );
309- if (peeled == PEELED_FULLY ||
310- (peeled == PEELED_TAGS && starts_with (refname , "refs/tags/" )))
311- last -> flag |= REF_KNOWS_PEELED ;
312- add_ref_entry (dir , last );
313- } else if (last &&
314- line .buf [0 ] == '^' &&
315- line .len == PEELED_LINE_LENGTH &&
316- line .buf [PEELED_LINE_LENGTH - 1 ] == '\n' &&
317- !get_oid_hex (line .buf + 1 , & oid )) {
318- oidcpy (& last -> u .value .peeled , & oid );
319300 /*
320301 * Regardless of what the file header said,
321302 * we definitely know the value of *this*
322303 * reference:
323304 */
324- last -> flag |= REF_KNOWS_PEELED ;
325- } else {
326- die_invalid_line ( refs -> path , line . buf , line . len ) ;
305+ entry -> flag |= REF_KNOWS_PEELED ;
306+
307+ pos = p ;
327308 }
328309
329- /* The "+ 1" is for the LF character. */
330- pos = eol + 1 ;
331- strbuf_reset (& line );
310+ strbuf_reset (& tmp );
332311 }
333312
334313 if (munmap (buf , size ))
335314 die_errno ("error ummapping packed-refs file" );
336315 close (fd );
337316
338- strbuf_release (& line );
317+ strbuf_release (& tmp );
339318 return packed_refs ;
340319}
341320
0 commit comments