Skip to content

Commit cec097b

Browse files
dschogitster
authored andcommitted
fsck: check tag objects' headers
We inspect commit objects pretty much in detail in git-fsck, but we just glanced over the tag objects. Let's be stricter. Since we do not want to limit 'tag' lines unduly, values that would fail the refname check only result in warnings, not errors. Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4d0d897 commit cec097b

File tree

1 file changed

+85
-1
lines changed

1 file changed

+85
-1
lines changed

fsck.c

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "commit.h"
77
#include "tag.h"
88
#include "fsck.h"
9+
#include "refs.h"
910

1011
static int fsck_walk_tree(struct tree *tree, fsck_walk_func walk, void *data)
1112
{
@@ -355,14 +356,97 @@ static int fsck_commit(struct commit *commit, const char *data,
355356
return ret;
356357
}
357358

359+
static int fsck_tag_buffer(struct tag *tag, const char *data,
360+
unsigned long size, fsck_error error_func)
361+
{
362+
unsigned char sha1[20];
363+
int ret = 0;
364+
const char *buffer;
365+
char *to_free = NULL, *eol;
366+
struct strbuf sb = STRBUF_INIT;
367+
368+
if (data)
369+
buffer = data;
370+
else {
371+
enum object_type type;
372+
373+
buffer = to_free =
374+
read_sha1_file(tag->object.sha1, &type, &size);
375+
if (!buffer)
376+
return error_func(&tag->object, FSCK_ERROR,
377+
"cannot read tag object");
378+
379+
if (type != OBJ_TAG) {
380+
ret = error_func(&tag->object, FSCK_ERROR,
381+
"expected tag got %s",
382+
typename(type));
383+
goto done;
384+
}
385+
}
386+
387+
if (require_end_of_header(buffer, size, &tag->object, error_func))
388+
goto done;
389+
390+
if (!skip_prefix(buffer, "object ", &buffer)) {
391+
ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'object' line");
392+
goto done;
393+
}
394+
if (get_sha1_hex(buffer, sha1) || buffer[40] != '\n') {
395+
ret = error_func(&tag->object, FSCK_ERROR, "invalid 'object' line format - bad sha1");
396+
goto done;
397+
}
398+
buffer += 41;
399+
400+
if (!skip_prefix(buffer, "type ", &buffer)) {
401+
ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'type' line");
402+
goto done;
403+
}
404+
eol = strchr(buffer, '\n');
405+
if (!eol) {
406+
ret = error_func(&tag->object, FSCK_ERROR, "invalid format - unexpected end after 'type' line");
407+
goto done;
408+
}
409+
if (type_from_string_gently(buffer, eol - buffer, 1) < 0)
410+
ret = error_func(&tag->object, FSCK_ERROR, "invalid 'type' value");
411+
if (ret)
412+
goto done;
413+
buffer = eol + 1;
414+
415+
if (!skip_prefix(buffer, "tag ", &buffer)) {
416+
ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'tag' line");
417+
goto done;
418+
}
419+
eol = strchr(buffer, '\n');
420+
if (!eol) {
421+
ret = error_func(&tag->object, FSCK_ERROR, "invalid format - unexpected end after 'type' line");
422+
goto done;
423+
}
424+
strbuf_addf(&sb, "refs/tags/%.*s", (int)(eol - buffer), buffer);
425+
if (check_refname_format(sb.buf, 0))
426+
error_func(&tag->object, FSCK_WARN, "invalid 'tag' name: %s", buffer);
427+
buffer = eol + 1;
428+
429+
if (!skip_prefix(buffer, "tagger ", &buffer))
430+
/* early tags do not contain 'tagger' lines; warn only */
431+
error_func(&tag->object, FSCK_WARN, "invalid format - expected 'tagger' line");
432+
else
433+
ret = fsck_ident(&buffer, &tag->object, error_func);
434+
435+
done:
436+
strbuf_release(&sb);
437+
free(to_free);
438+
return ret;
439+
}
440+
358441
static int fsck_tag(struct tag *tag, const char *data,
359442
unsigned long size, fsck_error error_func)
360443
{
361444
struct object *tagged = tag->tagged;
362445

363446
if (!tagged)
364447
return error_func(&tag->object, FSCK_ERROR, "could not load tagged object");
365-
return 0;
448+
449+
return fsck_tag_buffer(tag, data, size, error_func);
366450
}
367451

368452
int fsck_object(struct object *obj, void *data, unsigned long size,

0 commit comments

Comments
 (0)