mktag: use fsck instead of custom verify_tag()

Change the validation logic in "mktag" to use fsck's fsck_tag() instead of its own custom parser. Curiously the logic for both dates back to the same commit[1]. Let's unify them so we're not maintaining two sets functions to verify that a tag is OK. The behavior of fsck_tag() and the old "mktag" code being removed here is different in few aspects. I think it makes sense to remove some of those checks, namely: A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag code disallowed values larger than 1400. Yes there's currently no timezone with a greater offset[2], but since we allow any number of non-offical timezones (e.g. +1234) passing this through seems fine. Git also won't break in the future if e.g. French Polynesia decides it needs to outdo the Line Islands when it comes to timezone extravagance. B. fsck allows missing author names such as "tagger <email>", mktag wouldn't, but would allow e.g. "tagger [2 spaces] <email>" (but not "tagger [1 space] <email>"). Now we allow all of these. C. Like B, but "mktag" disallowed spaces in the <email> part, fsck allows it. In some ways fsck_tag() is stricter than "mktag" was, namely: D. fsck disallows zero-padded dates, but mktag didn't care. So e.g. the timestamp "0000000000 +0000" produces an error now. A test in "t1006-cat-file.sh" relied on this, it's been changed to use "hash-object" (without fsck) instead. There was one check I deemed worth keeping by porting it over to fsck_tag(): E. "mktag" did not allow any custom headers, and by extension (as an empty commit is allowed) also forbade an extra stray trailing newline after the headers it knew about. Add a new check in the "ignore" category to fsck and use it. This somewhat abuses the facility added in efaba7cc77f (fsck: optionally ignore specific fsck issues completely, 2015-06-22). This is somewhat of hack, but probably the least invasive change we can make here. The fsck command will shuffle these categories around, e.g. under --strict the "info" becomes a "warn" and "warn" becomes "error". Existing users of fsck's (and others, e.g. index-pack) --strict option rely on this. So we need to put something into a category that'll be ignored by all existing users of the API. Pretending that fsck.extraHeaderEntry=error ("ignore" by default) was set serves to do this for us. 1. ec4465adb38 (Add "tag" objects that can be used to sign other objects., 2005-04-25) 2. https://en.wikipedia.org/wiki/List_of_UTC_time_offsets Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Jan 5, 2021 at 20:42 UTC acf9de4c94e0de260f962dc04cc4f9007cedbf1a
6 files changed +127 -184
Documentation/git-mktag.txt
+8 -1
@@ -25,7 +25,14 @@ write a tag found in `my-tag`:
25 git hash-object -t tag -w --stdin <my-tag
26
27 The difference is that mktag will die before writing the tag if the
28 -tag doesn't pass a sanity check.
28 +tag doesn't pass a linkgit:git-fsck[1] check.
29 +
30 +The "fsck" check done mktag is stricter than what linkgit:git-fsck[1]
31 +would run by default in that all `fsck.<msg-id>` messages are promoted
32 +from warnings to errors (so e.g. a missing "tagger" line is an error).
33 +
34 +Extra headers in the object are also an error under mktag, but ignored
35 +by linkgit:git-fsck[1]
36
37 Tag Format
38 ----------
builtin/mktag.c
+50 -146
@@ -2,160 +2,60 @@
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)
@@ -164,10 +64,14 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
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");
fsck.c
+29 -3
@@ -80,7 +80,9 @@ static struct oidset gitmodules_done = OIDSET_INIT;
80 /* infos (reported as warnings, but ignored by default) */ \
81 FUNC(GITMODULES_PARSE, INFO) \
82 FUNC(BAD_TAG_NAME, INFO) \
83 - FUNC(MISSING_TAGGER_ENTRY, INFO)
83 + FUNC(MISSING_TAGGER_ENTRY, INFO) \
84 + /* ignored (elevated when requested) */ \
85 + FUNC(EXTRA_HEADER_ENTRY, IGNORE)
86
87 #define MSG_ID(id, msg_type) FSCK_MSG_##id,
88 enum fsck_msg_id {
@@ -911,6 +913,16 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
913 unsigned long size, struct fsck_options *options)
914 {
915 struct object_id tagged_oid;
916 + int tagged_type;
917 + return fsck_tag_standalone(oid, buffer, size, options, &tagged_oid,
918 + &tagged_type);
919 +}
920 +
921 +int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
922 + unsigned long size, struct fsck_options *options,
923 + struct object_id *tagged_oid,
924 + int *tagged_type)
925 +{
926 int ret = 0;
927 char *eol;
928 struct strbuf sb = STRBUF_INIT;
@@ -924,7 +936,7 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
936 ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
937 goto done;
938 }
927 - if (parse_oid_hex(buffer, &tagged_oid, &p) || *p != '\n') {
939 + if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
940 ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
941 if (ret)
942 goto done;
@@ -940,7 +952,8 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
952 ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
953 goto done;
954 }
943 - if (type_from_string_gently(buffer, eol - buffer, 1) < 0)
955 + *tagged_type = type_from_string_gently(buffer, eol - buffer, 1);
956 + if (*tagged_type < 0)
957 ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
958 if (ret)
959 goto done;
@@ -975,6 +988,19 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
988 else
989 ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
990
991 + if (!starts_with(buffer, "\n")) {
992 + /*
993 + * The verify_headers() check will allow
994 + * e.g. "[...]tagger <tagger>\nsome
995 + * garbage\n\nmessage" to pass, thinking "some
996 + * garbage" could be a custom header. E.g. "mktag"
997 + * doesn't want any unknown headers.
998 + */
999 + ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
1000 + if (ret)
1001 + goto done;
1002 + }
1003 +
1004 done:
1005 strbuf_release(&sb);
1006 return ret;
fsck.h
+9
@@ -62,6 +62,15 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
62 int fsck_object(struct object *obj, void *data, unsigned long size,
63 struct fsck_options *options);
64
65 +/*
66 + * fsck a tag, and pass info about it back to the caller. This is
67 + * exposed fsck_object() internals for git-mktag(1).
68 + */
69 +int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
70 + unsigned long size, struct fsck_options *options,
71 + struct object_id *tagged_oid,
72 + int *tag_type);
73 +
74 /*
75 * Some fsck checks are context-dependent, and may end up queued; run this
76 * after completing all fsck_object() calls in order to resolve any remaining
t/t1006-cat-file.sh
+1 -1
@@ -166,7 +166,7 @@ tag_content="$tag_header_without_timestamp 0000000000 +0000
166
167 $tag_description"
168
169 -tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
169 +tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
170 tag_size=$(strlen "$tag_content")
171
172 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
t/t3800-mktag.sh
+30 -33
@@ -53,7 +53,7 @@ too short for a tag
53 EOF
54
55 check_verify_failure 'Tag object length check' \
56 - '^error: .*size wrong.*$'
56 + '^error:.* missingObject:'
57
58 ############################################################
59 # 2. object line label check
@@ -66,7 +66,7 @@ tagger . <> 0 +0000
66
67 EOF
68
69 -check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
69 +check_verify_failure '"object" line label check' '^error:.* missingObject:'
70
71 ############################################################
72 # 3. object line hash check
@@ -79,7 +79,7 @@ tagger . <> 0 +0000
79
80 EOF
81
82 -check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
82 +check_verify_failure '"object" line check' '^error:.* badObjectSha1:'
83
84 ############################################################
85 # 4. type line label check
@@ -92,7 +92,7 @@ tagger . <> 0 +0000
92
93 EOF
94
95 -check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
95 +check_verify_failure '"type" line label check' '^error:.* missingTypeEntry:'
96
97 ############################################################
98 # 5. type line eol check
@@ -100,7 +100,7 @@ check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
100 echo "object $head" >tag.sig
101 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
102
103 -check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
103 +check_verify_failure '"type" line eol check' '^error:.* unterminatedHeader:'
104
105 ############################################################
106 # 6. tag line label check #1
@@ -114,7 +114,7 @@ tagger . <> 0 +0000
114 EOF
115
116 check_verify_failure '"tag" line label check #1' \
117 - '^error: char.*: no "tag " found$'
117 + '^error:.* missingTagEntry:'
118
119 ############################################################
120 # 7. tag line label check #2
@@ -126,7 +126,7 @@ tag
126 EOF
127
128 check_verify_failure '"tag" line label check #2' \
129 - '^error: char.*: no "tag " found$'
129 + '^error:.* badType:'
130
131 ############################################################
132 # 8. type line type-name length check
@@ -138,7 +138,7 @@ tag mytag
138 EOF
139
140 check_verify_failure '"type" line type-name length check' \
141 - '^error: char.*: type too long$'
141 + '^error:.* badType:'
142
143 ############################################################
144 # 9. verify object (hash/type) check
@@ -152,7 +152,7 @@ tagger . <> 0 +0000
152 EOF
153
154 check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
155 - '^error: char7: could not verify object.*$'
155 + '^fatal: could not read tagged object'
156
157 cat >tag.sig <<EOF
158 object $head
@@ -163,7 +163,7 @@ tagger . <> 0 +0000
163 EOF
164
165 check_verify_failure 'verify object (hash/type) check -- made-up type, valid object' \
166 - '^fatal: invalid object type'
166 + '^error:.* badType:'
167
168 cat >tag.sig <<EOF
169 object $(test_oid deadbeef)
@@ -174,7 +174,7 @@ tagger . <> 0 +0000
174 EOF
175
176 check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
177 - '^error: char7: could not verify object.*$'
177 + '^error:.* badType:'
178
179 cat >tag.sig <<EOF
180 object $head
@@ -185,7 +185,7 @@ tagger . <> 0 +0000
185 EOF
186
187 check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
188 - '^error: char7: could not verify object'
188 + '^fatal: object.*tagged as.*tree.*but is.*commit'
189
190 ############################################################
191 # 9.5. verify object (hash/type) check -- replacement
@@ -214,7 +214,7 @@ tagger . <> 0 +0000
214 EOF
215
216 check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
217 - '^error: char7: could not verify object'
217 + '^fatal: object.*tagged as.*tree.*but is.*blob'
218
219 ############################################################
220 # 10. verify tag-name check
@@ -228,7 +228,7 @@ tagger . <> 0 +0000
228 EOF
229
230 check_verify_failure 'verify tag-name check' \
231 - '^error: char.*: could not verify tag name$'
231 + '^error:.* badTagName:'
232
233 ############################################################
234 # 11. tagger line label check #1
@@ -242,7 +242,7 @@ This is filler
242 EOF
243
244 check_verify_failure '"tagger" line label check #1' \
245 - '^error: char.*: could not find "tagger "$'
245 + '^error:.* missingTaggerEntry:'
246
247 ############################################################
248 # 12. tagger line label check #2
@@ -257,10 +257,10 @@ This is filler
257 EOF
258
259 check_verify_failure '"tagger" line label check #2' \
260 - '^error: char.*: could not find "tagger "$'
260 + '^error:.* missingTaggerEntry:'
261
262 ############################################################
263 -# 13. disallow missing tag author name
263 +# 13. allow missing tag author name like fsck
264
265 cat >tag.sig <<EOF
266 object $head
@@ -271,8 +271,7 @@ tagger <> 0 +0000
271 This is filler
272 EOF
273
274 -check_verify_failure 'disallow missing tag author name' \
275 - '^error: char.*: missing tagger name$'
274 +test_expect_mktag_success 'allow missing tag author name'
275
276 ############################################################
277 # 14. disallow missing tag author name
@@ -287,7 +286,7 @@ tagger T A Gger <
286 EOF
287
288 check_verify_failure 'disallow malformed tagger' \
290 - '^error: char.*: malformed tagger field$'
289 + '^error:.* badEmail:'
290
291 ############################################################
292 # 15. allow empty tag email
@@ -303,7 +302,7 @@ EOF
302 test_expect_mktag_success 'allow empty tag email'
303
304 ############################################################
306 -# 16. disallow spaces in tag email
305 +# 16. allow spaces in tag email like fsck
306
307 cat >tag.sig <<EOF
308 object $head
@@ -313,8 +312,7 @@ tagger T A Gger <tag ger@example.com> 0 +0000
312
313 EOF
314
316 -check_verify_failure 'disallow spaces in tag email' \
317 - '^error: char.*: malformed tagger field$'
315 +test_expect_mktag_success 'allow spaces in tag email like fsck'
316
317 ############################################################
318 # 17. disallow missing tag timestamp
@@ -328,7 +326,7 @@ tagger T A Gger <tagger@example.com>__
326 EOF
327
328 check_verify_failure 'disallow missing tag timestamp' \
331 - '^error: char.*: missing tag timestamp$'
329 + '^error:.* badDate:'
330
331 ############################################################
332 # 18. detect invalid tag timestamp1
@@ -342,7 +340,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
340 EOF
341
342 check_verify_failure 'detect invalid tag timestamp1' \
345 - '^error: char.*: missing tag timestamp$'
343 + '^error:.* badDate:'
344
345 ############################################################
346 # 19. detect invalid tag timestamp2
@@ -356,7 +354,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
354 EOF
355
356 check_verify_failure 'detect invalid tag timestamp2' \
359 - '^error: char.*: malformed tag timestamp$'
357 + '^error:.* badDate:'
358
359 ############################################################
360 # 20. detect invalid tag timezone1
@@ -370,7 +368,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
368 EOF
369
370 check_verify_failure 'detect invalid tag timezone1' \
373 - '^error: char.*: malformed tag timezone$'
371 + '^error:.* badTimezone:'
372
373 ############################################################
374 # 21. detect invalid tag timezone2
@@ -384,10 +382,10 @@ tagger T A Gger <tagger@example.com> 1206478233 + 30
382 EOF
383
384 check_verify_failure 'detect invalid tag timezone2' \
387 - '^error: char.*: malformed tag timezone$'
385 + '^error:.* badTimezone:'
386
387 ############################################################
390 -# 22. detect invalid tag timezone3
388 +# 22. allow invalid tag timezone3 (the maximum is -1200/+1400)
389
390 cat >tag.sig <<EOF
391 object $head
@@ -397,8 +395,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
395
396 EOF
397
400 -check_verify_failure 'detect invalid tag timezone3' \
401 - '^error: char.*: malformed tag timezone$'
398 +test_expect_mktag_success 'allow invalid tag timezone'
399
400 ############################################################
401 # 23. detect invalid header entry
@@ -413,7 +410,7 @@ this line should not be here
410 EOF
411
412 check_verify_failure 'detect invalid header entry' \
416 - '^error: char.*: trailing garbage in tag header$'
413 + '^error:.* extraHeaderEntry:'
414
415 cat >tag.sig <<EOF
416 object $head
@@ -445,7 +442,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
442 EOF
443
444 check_verify_failure 'require a blank line before an empty body (2)' \
448 - '^error: char.*: trailing garbage in tag header$'
445 + '^error:.* extraHeaderEntry:'
446
447 ############################################################
448 # 24. create valid tag