2
#include "tag.h"
3
#include "replace-object.h"
4
#include "object-store.h"
5
+#include "fsck.h"
6
6
-/*
7
- * A signature file has a very simple fixed format: four lines
8
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
9
- * "tagger <committer>", followed by a blank line, a free-form tag
10
- * message and a signature block that git itself doesn't care about,
11
- * but that can be verified with gpg or similar.
12
- *
13
- * The first four lines are guaranteed to be at least 83 bytes:
14
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
15
- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
16
- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
17
- * the shortest possible tagger-line.
18
- */
19
-
20
-/*
21
- * We refuse to tag something we can't verify. Just because.
22
- */
23
-static int verify_object(const struct object_id *oid, const char *expected_type)
7
+static int mktag_fsck_error_func(struct fsck_options *o,
8
+ const struct object_id *oid,
9
+ enum object_type object_type,
10
+ int msg_type, const char *message)
11
{
25
- int ret = -1;
26
- enum object_type type;
27
- unsigned long size;
28
- void *buffer = read_object_file(oid, &type, &size);
29
- const struct object_id *repl = lookup_replace_object(the_repository, oid);
30
-
31
- if (buffer) {
32
- if (type == type_from_string(expected_type)) {
33
- ret = check_object_signature(the_repository, repl,
34
- buffer, size,
35
- expected_type);
36
- }
37
- free(buffer);
12
+ switch (msg_type) {
13
+ case FSCK_WARN:
14
+ case FSCK_ERROR:
15
+ /*
16
+ * We treat both warnings and errors as errors, things
17
+ * like missing "tagger" lines are "only" warnings
18
+ * under fsck, we've always considered them an error.
19
+ */
20
+ fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
21
+ return 1;
22
+ default:
23
+ BUG("%d (FSCK_IGNORE?) should never trigger this callback",
24
+ msg_type);
25
}
39
- return ret;
26
}
27
42
-static int verify_tag(char *buffer, unsigned long size)
28
+static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
29
{
44
- int typelen;
45
- char type[20];
46
- struct object_id oid;
47
- const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
48
- size_t len;
49
-
50
- if (size < 84)
51
- return error("wanna fool me ? you obviously got the size wrong !");
52
-
53
- buffer[size] = 0;
54
-
55
- /* Verify object line */
56
- object = buffer;
57
- if (memcmp(object, "object ", 7))
58
- return error("char%d: does not start with \"object \"", 0);
59
-
60
- if (parse_oid_hex(object + 7, &oid, &p))
61
- return error("char%d: could not get SHA1 hash", 7);
62
-
63
- /* Verify type line */
64
- type_line = p + 1;
65
- if (memcmp(type_line - 1, "\ntype ", 6))
66
- return error("char%d: could not find \"\\ntype \"", 47);
67
-
68
- /* Verify tag-line */
69
- tag_line = strchr(type_line, '\n');
70
- if (!tag_line)
71
- return error("char%"PRIuMAX": could not find next \"\\n\"",
72
- (uintmax_t) (type_line - buffer));
73
- tag_line++;
74
- if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
75
- return error("char%"PRIuMAX": no \"tag \" found",
76
- (uintmax_t) (tag_line - buffer));
77
-
78
- /* Get the actual type */
79
- typelen = tag_line - type_line - strlen("type \n");
80
- if (typelen >= sizeof(type))
81
- return error("char%"PRIuMAX": type too long",
82
- (uintmax_t) (type_line+5 - buffer));
83
-
84
- memcpy(type, type_line+5, typelen);
85
- type[typelen] = 0;
86
-
87
- /* Verify that the object matches */
88
- if (verify_object(&oid, type))
89
- return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
90
-
91
- /* Verify the tag-name: we don't allow control characters or spaces in it */
92
- tag_line += 4;
93
- for (;;) {
94
- unsigned char c = *tag_line++;
95
- if (c == '\n')
96
- break;
97
- if (c > ' ')
98
- continue;
99
- return error("char%"PRIuMAX": could not verify tag name",
100
- (uintmax_t) (tag_line - buffer));
101
- }
102
-
103
- /* Verify the tagger line */
104
- tagger_line = tag_line;
105
-
106
- if (memcmp(tagger_line, "tagger ", 7))
107
- return error("char%"PRIuMAX": could not find \"tagger \"",
108
- (uintmax_t) (tagger_line - buffer));
109
-
110
- /*
111
- * Check for correct form for name and email
112
- * i.e. " <" followed by "> " on _this_ line
113
- * No angle brackets within the name or email address fields.
114
- * No spaces within the email address field.
115
- */
116
- tagger_line += 7;
117
- if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
118
- strpbrk(tagger_line, "<>\n") != lb+1 ||
119
- strpbrk(lb+2, "><\n ") != rb)
120
- return error("char%"PRIuMAX": malformed tagger field",
121
- (uintmax_t) (tagger_line - buffer));
122
-
123
- /* Check for author name, at least one character, space is acceptable */
124
- if (lb == tagger_line)
125
- return error("char%"PRIuMAX": missing tagger name",
126
- (uintmax_t) (tagger_line - buffer));
127
-
128
- /* timestamp, 1 or more digits followed by space */
129
- tagger_line = rb + 2;
130
- if (!(len = strspn(tagger_line, "0123456789")))
131
- return error("char%"PRIuMAX": missing tag timestamp",
132
- (uintmax_t) (tagger_line - buffer));
133
- tagger_line += len;
134
- if (*tagger_line != ' ')
135
- return error("char%"PRIuMAX": malformed tag timestamp",
136
- (uintmax_t) (tagger_line - buffer));
137
- tagger_line++;
138
-
139
- /* timezone, 5 digits [+-]hhmm, max. 1400 */
140
- if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
141
- strspn(tagger_line+1, "0123456789") == 4 &&
142
- tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
143
- return error("char%"PRIuMAX": malformed tag timezone",
144
- (uintmax_t) (tagger_line - buffer));
145
- tagger_line += 6;
146
-
147
- /* Verify the blank line separating the header from the body */
148
- if (*tagger_line != '\n')
149
- return error("char%"PRIuMAX": trailing garbage in tag header",
150
- (uintmax_t) (tagger_line - buffer));
30
+ int ret;
31
+ enum object_type type;
32
+ unsigned long size;
33
+ void *buffer;
34
+ const struct object_id *repl;
35
+
36
+ buffer = read_object_file(tagged_oid, &type, &size);
37
+ if (!buffer)
38
+ die("could not read tagged object '%s'",
39
+ oid_to_hex(tagged_oid));
40
+ if (type != *tagged_type)
41
+ die("object '%s' tagged as '%s', but is a '%s' type",
42
+ oid_to_hex(tagged_oid),
43
+ type_name(*tagged_type), type_name(type));
44
+
45
+ repl = lookup_replace_object(the_repository, tagged_oid);
46
+ ret = check_object_signature(the_repository, repl,
47
+ buffer, size, type_name(*tagged_type));
48
+ free(buffer);
49
152
- /* The actual stuff afterwards we don't care about.. */
153
- return 0;
50
+ return ret;
51
}
52
53
int cmd_mktag(int argc, const char **argv, const char *prefix)
54
{
55
struct strbuf buf = STRBUF_INIT;
56
+ struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
57
+ struct object_id tagged_oid;
58
+ int tagged_type;
59
struct object_id result;
60
61
if (argc != 1)
64
if (strbuf_read(&buf, 0, 0) < 0)
65
die_errno("could not read from stdin");
66
167
- /* Verify it for some basic sanity: it needs to start with
168
- "object <sha1>\ntype\ntagger " */
169
- if (verify_tag(buf.buf, buf.len) < 0)
170
- die("invalid tag signature file");
67
+ fsck_options.error_func = mktag_fsck_error_func;
68
+ fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
69
+ if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
70
+ &tagged_oid, &tagged_type))
71
+ die("tag on stdin did not pass our strict fsck check");
72
+
73
+ if (verify_object_in_tag(&tagged_oid, &tagged_type))
74
+ die("tag on stdin did not refer to a valid object");
75
76
if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
77
die("unable to write tag file");