git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 07/10] mktag: use fsck instead of custom verify_tag()

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Dec 9, 2020, 20:01 UTC
Message-ID
<20201209200140.29425-8-avarab@gmail.com>
In-Reply-To
<20201126222257.5629-1-avarab@gmail.com>

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>
---
 builtin/mktag.c     | 196 +++++++++++---------------------------------
 fsck.c              |  32 +++++++-
 fsck.h              |   9 ++
 t/t1006-cat-file.sh |   2 +-
 t/t3800-mktag.sh    |  79 +++++++++++-------
 5 files changed, 137 insertions(+), 181 deletions(-)
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 97ca5f28b1b..5765cde0032 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -2,160 +2,60 @@
 #include "tag.h"
 #include "replace-object.h"
 #include "object-store.h"
+#include "fsck.h"
 
-/*
- * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
- * "tagger <committer>", followed by a blank line, a free-form tag
- * message and a signature block that git itself doesn't care about,
- * but that can be verified with gpg or similar.
- *
- * The first four lines are guaranteed to be at least 83 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
- * the shortest possible tagger-line.
- */
-
-/*
- * We refuse to tag something we can't verify. Just because.
- */
-static int verify_object(const struct object_id *oid, const char *expected_type)
+static int mktag_fsck_error_func(struct fsck_options *o,
+				 const struct object_id *oid,
+				 enum object_type object_type,
+				 int msg_type, const char *message)
 {
-	int ret = -1;
-	enum object_type type;
-	unsigned long size;
-	void *buffer = read_object_file(oid, &type, &size);
-	const struct object_id *repl = lookup_replace_object(the_repository, oid);
-
-	if (buffer) {
-		if (type == type_from_string(expected_type)) {
-			ret = check_object_signature(the_repository, repl,
-						     buffer, size,
-						     expected_type);
-		}
-		free(buffer);
+	switch (msg_type) {
+	case FSCK_WARN:
+	case FSCK_ERROR:
+		/*
+		 * We treat both warnings and errors as errors, things
+		 * like missing "tagger" lines are "only" warnings
+		 * under fsck, we've always considered them an error.
+		 */
+		fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
+		return 1;
+	default:
+		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
+		    msg_type);
 	}
-	return ret;
 }
 
-static int verify_tag(char *buffer, unsigned long size)
+static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 {
-	int typelen;
-	char type[20];
-	struct object_id oid;
-	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
-	size_t len;
-
-	if (size < 84)
-		return error("wanna fool me ? you obviously got the size wrong !");
-
-	buffer[size] = 0;
-
-	/* Verify object line */
-	object = buffer;
-	if (memcmp(object, "object ", 7))
-		return error("char%d: does not start with \"object \"", 0);
-
-	if (parse_oid_hex(object + 7, &oid, &p))
-		return error("char%d: could not get SHA1 hash", 7);
-
-	/* Verify type line */
-	type_line = p + 1;
-	if (memcmp(type_line - 1, "\ntype ", 6))
-		return error("char%d: could not find \"\\ntype \"", 47);
-
-	/* Verify tag-line */
-	tag_line = strchr(type_line, '\n');
-	if (!tag_line)
-		return error("char%"PRIuMAX": could not find next \"\\n\"",
-				(uintmax_t) (type_line - buffer));
-	tag_line++;
-	if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
-		return error("char%"PRIuMAX": no \"tag \" found",
-				(uintmax_t) (tag_line - buffer));
-
-	/* Get the actual type */
-	typelen = tag_line - type_line - strlen("type \n");
-	if (typelen >= sizeof(type))
-		return error("char%"PRIuMAX": type too long",
-				(uintmax_t) (type_line+5 - buffer));
-
-	memcpy(type, type_line+5, typelen);
-	type[typelen] = 0;
-
-	/* Verify that the object matches */
-	if (verify_object(&oid, type))
-		return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
-
-	/* Verify the tag-name: we don't allow control characters or spaces in it */
-	tag_line += 4;
-	for (;;) {
-		unsigned char c = *tag_line++;
-		if (c == '\n')
-			break;
-		if (c > ' ')
-			continue;
-		return error("char%"PRIuMAX": could not verify tag name",
-				(uintmax_t) (tag_line - buffer));
-	}
-
-	/* Verify the tagger line */
-	tagger_line = tag_line;
-
-	if (memcmp(tagger_line, "tagger ", 7))
-		return error("char%"PRIuMAX": could not find \"tagger \"",
-			(uintmax_t) (tagger_line - buffer));
-
-	/*
-	 * Check for correct form for name and email
-	 * i.e. " <" followed by "> " on _this_ line
-	 * No angle brackets within the name or email address fields.
-	 * No spaces within the email address field.
-	 */
-	tagger_line += 7;
-	if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
-		strpbrk(tagger_line, "<>\n") != lb+1 ||
-		strpbrk(lb+2, "><\n ") != rb)
-		return error("char%"PRIuMAX": malformed tagger field",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* Check for author name, at least one character, space is acceptable */
-	if (lb == tagger_line)
-		return error("char%"PRIuMAX": missing tagger name",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* timestamp, 1 or more digits followed by space */
-	tagger_line = rb + 2;
-	if (!(len = strspn(tagger_line, "0123456789")))
-		return error("char%"PRIuMAX": missing tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += len;
-	if (*tagger_line != ' ')
-		return error("char%"PRIuMAX": malformed tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line++;
-
-	/* timezone, 5 digits [+-]hhmm, max. 1400 */
-	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
-	      strspn(tagger_line+1, "0123456789") == 4 &&
-	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
-		return error("char%"PRIuMAX": malformed tag timezone",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += 6;
-
-	/* Verify the blank line separating the header from the body */
-	if (*tagger_line != '\n')
-		return error("char%"PRIuMAX": trailing garbage in tag header",
-			(uintmax_t) (tagger_line - buffer));
+	int ret;
+	enum object_type type;
+	unsigned long size;
+	void *buffer;
+	const struct object_id *repl;
+
+	buffer = read_object_file(tagged_oid, &type, &size);
+	if (!buffer)
+		die("could not read tagged object '%s'\n",
+		    oid_to_hex(tagged_oid));
+	if (type != *tagged_type)
+		die("object '%s' tagged as '%s', but is a '%s' type\n",
+		    oid_to_hex(tagged_oid),
+		    type_name(*tagged_type), type_name(type));
+
+	repl = lookup_replace_object(the_repository, tagged_oid);
+	ret = check_object_signature(the_repository, repl,
+				     buffer, size, type_name(*tagged_type));
+	free(buffer);
 
-	/* The actual stuff afterwards we don't care about.. */
-	return 0;
+	return ret;
 }
 
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf = STRBUF_INIT;
+	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+	struct object_id tagged_oid;
+	int tagged_type;
 	struct object_id result;
 
 	if (argc != 1)
@@ -164,10 +64,14 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
 
-	/* Verify it for some basic sanity: it needs to start with
-	   "object <sha1>\ntype\ntagger " */
-	if (verify_tag(buf.buf, buf.len) < 0)
-		die("invalid tag signature file");
+	fsck_options.error_func = mktag_fsck_error_func;
+	fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
+	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
+				&tagged_oid, &tagged_type))
+		die("tag on stdin did not pass our strict fsck check");
+
+	if (verify_object_in_tag(&tagged_oid, &tagged_type))
+		die("tag on stdin did not refer to a valid object");
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
 		die("unable to write tag file");
diff --git a/fsck.c b/fsck.c
index f82e2fe9e30..bed5e20e03b 100644
--- a/fsck.c
+++ b/fsck.c
@@ -80,7 +80,9 @@ static struct oidset gitmodules_done = OIDSET_INIT;
 	/* infos (reported as warnings, but ignored by default) */ \
 	FUNC(GITMODULES_PARSE, INFO) \
 	FUNC(BAD_TAG_NAME, INFO) \
-	FUNC(MISSING_TAGGER_ENTRY, INFO)
+	FUNC(MISSING_TAGGER_ENTRY, INFO) \
+	/* ignored (elevated when requested) */ \
+	FUNC(EXTRA_HEADER_ENTRY, IGNORE)
 
 #define MSG_ID(id, msg_type) FSCK_MSG_##id,
 enum fsck_msg_id {
@@ -911,6 +913,16 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		    unsigned long size, struct fsck_options *options)
 {
 	struct object_id tagged_oid;
+	int tagged_type;
+	return fsck_tag_standalone(oid, buffer, size, options, &tagged_oid,
+				   &tagged_type);
+}
+
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tagged_type)
+{
 	int ret = 0;
 	char *eol;
 	struct strbuf sb = STRBUF_INIT;
@@ -924,7 +936,7 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
 		goto done;
 	}
-	if (parse_oid_hex(buffer, &tagged_oid, &p) || *p != '\n') {
+	if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
 		if (ret)
 			goto done;
@@ -940,7 +952,8 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
 		goto done;
 	}
-	if (type_from_string_gently(buffer, eol - buffer, 1) < 0)
+	*tagged_type = type_from_string_gently(buffer, eol - buffer, 1);
+	if (*tagged_type < 0)
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
 	if (ret)
 		goto done;
@@ -975,6 +988,19 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 	else
 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
 
+	if (!starts_with(buffer, "\n")) {
+		/*
+		 * The verify_headers() check will allow
+		 * e.g. "[...]tagger <tagger>\nsome
+		 * garbage\n\nmessage" to pass, thinking "some
+		 * garbage" could be a custom header. E.g. "mktag"
+		 * doesn't want any unknown headers.
+		 */
+		ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
+		if (ret)
+			goto done;
+	}
+
 done:
 	strbuf_release(&sb);
 	return ret;
diff --git a/fsck.h b/fsck.h
index 69cf715e798..29ee4c45e87 100644
--- a/fsck.h
+++ b/fsck.h
@@ -62,6 +62,15 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
 int fsck_object(struct object *obj, void *data, unsigned long size,
 	struct fsck_options *options);
 
+/*
+ * fsck a tag, and pass info about it back to the caller. This is
+ * exposed fsck_object() internals for git-mktag(1).
+ */
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tag_type);
+
 /*
  * Some fsck checks are context-dependent, and may end up queued; run this
  * after completing all fsck_object() calls in order to resolve any remaining
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 2f501d2dc94..5d2dc99b74a 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -166,7 +166,7 @@ tag_content="$tag_header_without_timestamp 0000000000 +0000
 
 $tag_description"
 
-tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
+tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
 tag_size=$(strlen "$tag_content")
 
 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 9ae1b0bb0af..19b3c1bca9c 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -37,7 +37,7 @@ too short for a tag
 EOF
 
 check_verify_failure 'Tag object length check' \
-	'^error: .*size wrong.*$'
+	'^error:.* missingObject:'
 
 ############################################################
 #  2. object line label check
@@ -50,7 +50,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
+check_verify_failure '"object" line label check' '^error:.* missingObject:'
 
 ############################################################
 #  3. object line hash check
@@ -63,7 +63,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
+check_verify_failure '"object" line check' '^error:.* badObjectSha1:'
 
 ############################################################
 #  4. type line label check
@@ -76,7 +76,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
+check_verify_failure '"type" line label check' '^error:.* missingTypeEntry:'
 
 ############################################################
 #  5. type line eol check
@@ -84,7 +84,7 @@ check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
 echo "object $head" >tag.sig
 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
 
-check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
+check_verify_failure '"type" line eol check' '^error:.* unterminatedHeader:'
 
 ############################################################
 #  6. tag line label check #1
@@ -98,7 +98,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure '"tag" line label check #1' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* missingTagEntry:'
 
 ############################################################
 #  7. tag line label check #2
@@ -110,7 +110,7 @@ tag
 EOF
 
 check_verify_failure '"tag" line label check #2' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* badType:'
 
 ############################################################
 #  8. type line type-name length check
@@ -122,7 +122,7 @@ tag mytag
 EOF
 
 check_verify_failure '"type" line type-name length check' \
-	'^error: char.*: type too long$'
+	'^error:.* badType:'
 
 ############################################################
 #  9. verify object (hash/type) check
@@ -136,7 +136,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
-	'^error: char7: could not verify object.*$'
+	'^fatal: could not read tagged object'
 
 cat >tag.sig <<EOF
 object $head
@@ -147,7 +147,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
-	'^fatal: invalid object type'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
@@ -158,7 +158,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
-	'^error: char7: could not verify object.*$'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $head
@@ -169,7 +169,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
-	'^error: char7: could not verify object'
+	'^fatal: object.*tagged as.*tree.*but is.*commit'
 
 ############################################################
 # 10. verify tag-name check
@@ -183,7 +183,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error: char.*: could not verify tag name$'
+	'^error:.* badTagName:'
 
 ############################################################
 # 11. tagger line label check #1
@@ -197,7 +197,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
 # 12. tagger line label check #2
@@ -212,10 +212,10 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
-# 13. disallow missing tag author name
+# 13. allow missing tag author name like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -226,8 +226,9 @@ tagger  <> 0 +0000
 This is filler
 EOF
 
-check_verify_failure 'disallow missing tag author name' \
-	'^error: char.*: missing tagger name$'
+test_expect_success 'allow missing tag author name' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 14. disallow missing tag author name
@@ -242,7 +243,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error: char.*: malformed tagger field$'
+	'^error:.* badEmail:'
 
 ############################################################
 # 15. allow empty tag email
@@ -260,7 +261,7 @@ test_expect_success \
     'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
 
 ############################################################
-# 16. disallow spaces in tag email
+# 16. allow spaces in tag email like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -270,8 +271,9 @@ tagger T A Gger <tag ger@example.com> 0 +0000
 
 EOF
 
-check_verify_failure 'disallow spaces in tag email' \
-	'^error: char.*: malformed tagger field$'
+test_expect_success 'allow spaces in tag email like fsck' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 17. disallow missing tag timestamp
@@ -285,7 +287,7 @@ tagger T A Gger <tagger@example.com>__
 EOF
 
 check_verify_failure 'disallow missing tag timestamp' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 18. detect invalid tag timestamp1
@@ -299,7 +301,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
 EOF
 
 check_verify_failure 'detect invalid tag timestamp1' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 19. detect invalid tag timestamp2
@@ -313,7 +315,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
 EOF
 
 check_verify_failure 'detect invalid tag timestamp2' \
-	'^error: char.*: malformed tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 20. detect invalid tag timezone1
@@ -327,7 +329,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
 EOF
 
 check_verify_failure 'detect invalid tag timezone1' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 ############################################################
 # 21. detect invalid tag timezone2
@@ -341,10 +343,10 @@ tagger T A Gger <tagger@example.com> 1206478233 +  30
 EOF
 
 check_verify_failure 'detect invalid tag timezone2' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 ############################################################
-# 22. detect invalid tag timezone3
+# 22. allow invalid tag timezone3 (the maximum is -1200/+1400)
 
 cat >tag.sig <<EOF
 object $head
@@ -354,8 +356,9 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
 
 EOF
 
-check_verify_failure 'detect invalid tag timezone3' \
-	'^error: char.*: malformed tag timezone$'
+test_expect_success 'allow invalid tag timezone' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 23. detect invalid header entry
@@ -370,7 +373,21 @@ this line should not be here
 EOF
 
 check_verify_failure 'detect invalid header entry' \
-	'^error: char.*: trailing garbage in tag header$'
+	'^error:.* extraHeaderEntry:'
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+
+
+this line comes after an extra newline
+EOF
+
+test_expect_success \
+    'allow extra newlines at start of body' \
+    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
 
 ############################################################
 # 24. create valid tag
-- 
2.29.2.222.g5d2a92d10f8
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 57 of 229 in “Hash-independent tests, part 5”
  1. 00/14 Hash-independent tests, part 5brian m. carlson, Aug 18, 2019
  2. 01/14 t3201: abstract away SHA-1-specific constantsbrian m. carlson, Aug 18, 2019
  3. 02/14 t3206: abstract away hash size constantsbrian m. carlson, Aug 18, 2019
  4. 04/14 t3305: make hash size independentbrian m. carlson, Aug 18, 2019
  5. 03/14 t3301: abstract away SHA-1-specific constantsbrian m. carlson, Aug 18, 2019
  6. 05/14 t3306: abstract away SHA-1-specific constantsbrian m. carlson, Aug 18, 2019
  7. 06/14 t3404: abstract away SHA-1-specific constantsbrian m. carlson, Aug 18, 2019
  8. 07/14 t3430: avoid hard-coded object IDsbrian m. carlson, Aug 18, 2019
  9. 08/14 t3506: make hash independentbrian m. carlson, Aug 18, 2019
  10. 10/14 t3800: make hash-size independentbrian m. carlson, Aug 18, 2019
  11. 11/14 t3903: abstract away SHA-1-specific constantsbrian m. carlson, Aug 18, 2019
  12. Eric SunshineAug 18, 2019
  13. brian m. carlsonAug 18, 2019
  14. 12/14 t4000: make hash size independentbrian m. carlson, Aug 18, 2019
  15. 13/14 t4002: make hash independentbrian m. carlson, Aug 18, 2019
  16. Eric SunshineAug 18, 2019
  17. 14/14 t4009: make hash size independentbrian m. carlson, Aug 18, 2019
  18. 09/14 t3600: make hash size independentbrian m. carlson, Aug 18, 2019
  19. 00/14 Hash-independent tests, part 5brian m. carlson, Aug 26, 2019
  20. 01/14 t3201: abstract away SHA-1-specific constantsbrian m. carlson, Aug 26, 2019
  21. 04/14 t3305: make hash size independentbrian m. carlson, Aug 26, 2019
  22. 03/14 t3301: abstract away SHA-1-specific constantsbrian m. carlson, Aug 26, 2019
  23. 02/14 t3206: abstract away hash size constantsbrian m. carlson, Aug 26, 2019
  24. 07/14 t3430: avoid hard-coded object IDsbrian m. carlson, Aug 26, 2019
  25. 05/14 t3306: abstract away SHA-1-specific constantsbrian m. carlson, Aug 26, 2019
  26. 08/14 t3506: make hash independentbrian m. carlson, Aug 26, 2019
  27. 06/14 t3404: abstract away SHA-1-specific constantsbrian m. carlson, Aug 26, 2019
  28. 09/14 t3600: make hash size independentbrian m. carlson, Aug 26, 2019
  29. 10/14 t3800: make hash-size independentbrian m. carlson, Aug 26, 2019
  30. mktag: don't check SHA-1 object length under SHA-256Ævar Arnfjörð Bjarmason, Nov 23, 2020
  31. Junio C HamanoNov 23, 2020
  32. Jeff KingNov 23, 2020
  33. Junio C HamanoNov 23, 2020
  34. Jeff KingNov 24, 2020
  35. Jeff KingNov 23, 2020
  36. brian m. carlsonNov 24, 2020
  37. 01/12 mktag: use default strbuf_read() hintÆvar Arnfjörð Bjarmason, Nov 26, 2020
  38. 00/12 make "mktag" use fsck_tag()Ævar Arnfjörð Bjarmason, Nov 26, 2020
  39. 02/10 mktag: use default strbuf_read() hintÆvar Arnfjörð Bjarmason, Nov 26, 2020
  40. Junio C HamanoDec 1, 2020
  41. 04/10 mktag: remove redundant braces in one-line body "if"Ævar Arnfjörð Bjarmason, Nov 26, 2020
  42. 03/10 mktag: reword write_object_file() errorÆvar Arnfjörð Bjarmason, Nov 26, 2020
  43. Junio C HamanoDec 1, 2020
  44. Junio C HamanoDec 1, 2020
  45. 00/10 make "mktag" use fsck_tag()Ævar Arnfjörð Bjarmason, Nov 26, 2020
  46. Ævar Arnfjörð BjarmasonDec 1, 2020
  47. Junio C HamanoDec 1, 2020
  48. Junio C HamanoDec 2, 2020
  49. Ævar Arnfjörð BjarmasonDec 3, 2020
  50. 02/10 mktag: use default strbuf_read() hintÆvar Arnfjörð Bjarmason, Dec 9, 2020
  51. 01/10 mktag doc: say <hash> not <sha1>Ævar Arnfjörð Bjarmason, Dec 9, 2020
  52. 03/10 mktag: remove redundant braces in one-line body "if"Ævar Arnfjörð Bjarmason, Dec 9, 2020
  53. 06/10 mktag tests: improve verify_object() test coverageÆvar Arnfjörð Bjarmason, Dec 9, 2020
  54. 10/10 mktag: allow turning off fsck.extraHeaderEntryÆvar Arnfjörð Bjarmason, Dec 9, 2020
  55. 08/10 mktag doc: update to explain why to use thisÆvar Arnfjörð Bjarmason, Dec 9, 2020
  56. 09/10 fsck: make fsck_config() re-usableÆvar Arnfjörð Bjarmason, Dec 9, 2020
  57. 07/10 mktag: use fsck instead of custom verify_tag()Ævar Arnfjörð Bjarmason, Dec 9, 2020
  58. 00/10 make "mktag" use fsck_tag()Ævar Arnfjörð Bjarmason, Dec 9, 2020
  59. Junio C HamanoDec 9, 2020
  60. 01/20 mktag doc: say <hash> not <sha1>Ævar Arnfjörð Bjarmason, Dec 23, 2020
  61. 00/20 make "mktag" use fsck_tag() & moreÆvar Arnfjörð Bjarmason, Dec 23, 2020
  62. Junio C HamanoDec 23, 2020
  63. Junio C HamanoDec 24, 2020
  64. 00/23 make "mktag" use fsck_tag() & moreÆvar Arnfjörð Bjarmason, Jan 5, 2021
  65. 01/23 mktag doc: say <hash> not <sha1>Ævar Arnfjörð Bjarmason, Jan 5, 2021
  66. 03/23 mktag doc: update to explain why to use thisÆvar Arnfjörð Bjarmason, Jan 5, 2021
  67. 04/23 mktag tests: don't needlessly use a subshellÆvar Arnfjörð Bjarmason, Jan 5, 2021
  68. 02/23 mktag doc: grammar fix, when exists -> when it existsÆvar Arnfjörð Bjarmason, Jan 5, 2021
  69. 06/23 mktag tests: remove needless SHA-1 hardcodingÆvar Arnfjörð Bjarmason, Jan 5, 2021
  70. 05/23 mktag tests: use "test_commit" helperÆvar Arnfjörð Bjarmason, Jan 5, 2021
  71. 07/23 mktag tests: don't redirect stderr to a file needlesslyÆvar Arnfjörð Bjarmason, Jan 5, 2021
  72. 08/23 mktag tests: don't create "mytag" twiceÆvar Arnfjörð Bjarmason, Jan 5, 2021
  73. 11/23 mktag tests: test "hash-object" compatibilityÆvar Arnfjörð Bjarmason, Jan 5, 2021
  74. 13/23 mktag tests: test verify_object() with replaced objectsÆvar Arnfjörð Bjarmason, Jan 5, 2021
  75. 12/23 mktag tests: improve verify_object() test coverageÆvar Arnfjörð Bjarmason, Jan 5, 2021
  76. SZEDER GáborJan 10, 2021
  77. Should you use test_i18ngrep or GIT_TEST_GETTEXT_POISON=false?Ævar Arnfjörð Bjarmason, Jan 10, 2021
  78. Junio C HamanoJan 10, 2021
  79. Ævar Arnfjörð BjarmasonJan 11, 2021
  80. 0/2 Makefile & gettext.c: remove warning & long commentÆvar Arnfjörð Bjarmason, Jan 11, 2021
  81. Junio C HamanoJan 11, 2021
  82. 2/2 gettext.c: remove/reword a mostly-useless commentÆvar Arnfjörð Bjarmason, Jan 11, 2021
  83. 1/2 Makefile: remove a warning about old GETTEXT_POISON flagÆvar Arnfjörð Bjarmason, Jan 11, 2021
  84. 2/6 tests: remove support for GIT_TEST_GETTEXT_POISONÆvar Arnfjörð Bjarmason, Jan 11, 2021
  85. Junio C HamanoJan 11, 2021
  86. config.c: remove last remnant of GIT_TEST_GETTEXT_POISONÆvar Arnfjörð Bjarmason, Mar 24, 2021
  87. Jeff KingMar 25, 2021
  88. Ævar Arnfjörð BjarmasonMar 25, 2021
  89. Junio C HamanoMar 25, 2021
  90. config.c: remove last remnant of GIT_TEST_GETTEXT_POISONÆvar Arnfjörð Bjarmason, Apr 8, 2021
  91. Junio C HamanoApr 8, 2021
  92. 0/6 Remove GIT_TEST_GETTEXT_POISON facilityÆvar Arnfjörð Bjarmason, Jan 11, 2021
  93. SZEDER GáborJan 20, 2021
  94. Ævar Arnfjörð BjarmasonJan 20, 2021
  95. 3/3 tests: remove uses of GIT_TEST_GETTEXT_POISON=falseÆvar Arnfjörð Bjarmason, Jan 20, 2021
  96. 2/3 tests: remove support for GIT_TEST_GETTEXT_POISONÆvar Arnfjörð Bjarmason, Jan 20, 2021
  97. 0/3 Remove GIT_TEST_GETTEXT_POISON facilityÆvar Arnfjörð Bjarmason, Jan 20, 2021
  98. 1/4 tests: remove last uses of GIT_TEST_GETTEXT_POISON=falseÆvar Arnfjörð Bjarmason, Feb 11, 2021
  99. mktag tests: fix broken "&&" chainÆvar Arnfjörð Bjarmason, Mar 7, 2021
  100. SZEDER GáborMar 7, 2021
  101. Junio C HamanoMar 7, 2021
  102. Eric SunshineMar 7, 2021
  103. mktag tests: fix broken "&&" chainÆvar Arnfjörð Bjarmason, Mar 24, 2021
  104. Junio C HamanoMar 24, 2021
  105. 3/4 tests: remove last uses of C_LOCALE_OUTPUTÆvar Arnfjörð Bjarmason, Feb 11, 2021
  106. 0/4 More GETTEXT_POISON removalÆvar Arnfjörð Bjarmason, Feb 11, 2021
  107. 2/4 tests: remove most uses of C_LOCALE_OUTPUTÆvar Arnfjörð Bjarmason, Feb 11, 2021
  108. 4/4 tests: remove most uses of test_i18ncmpÆvar Arnfjörð Bjarmason, Feb 11, 2021
  109. Junio C HamanoFeb 11, 2021
  110. Ævar Arnfjörð BjarmasonFeb 13, 2021
  111. Jonathan NiederFeb 19, 2021
  112. tests: remove all uses of test_i18cmpÆvar Arnfjörð Bjarmason, Apr 13, 2021
  113. 0/2 diff tests: un-flaky and post-gettext-poison cleanupÆvar Arnfjörð Bjarmason, Apr 13, 2021
  114. 2/2 diff tests: rewrite flakyness-causing test "aid"Ævar Arnfjörð Bjarmason, Apr 13, 2021
  115. Matheus Tavares BernardinoApr 13, 2021
  116. Ævar Arnfjörð BjarmasonApr 13, 2021
  117. Matheus Tavares BernardinoApr 13, 2021
  118. Junio C HamanoApr 13, 2021
  119. Ævar Arnfjörð BjarmasonApr 14, 2021
  120. Junio C HamanoApr 14, 2021
  121. Ævar Arnfjörð BjarmasonApr 14, 2021
  122. Junio C HamanoApr 14, 2021
  123. Ævar Arnfjörð BjarmasonApr 14, 2021
  124. Junio C HamanoApr 15, 2021
  125. Ævar Arnfjörð BjarmasonApr 15, 2021
  126. Junio C HamanoApr 16, 2021
  127. SZEDER GáborApr 15, 2021
  128. 1/2 diff tests: remove redundant case statementÆvar Arnfjörð Bjarmason, Apr 13, 2021
  129. Matheus Tavares BernardinoApr 13, 2021
  130. Ævar Arnfjörð BjarmasonApr 13, 2021
  131. Junio C HamanoApr 13, 2021
  132. 1/3 ci: remove GETTEXT_POISON jobsÆvar Arnfjörð Bjarmason, Jan 20, 2021
  133. 1/6 ci: remove GETTEXT_POISON jobsÆvar Arnfjörð Bjarmason, Jan 11, 2021
  134. SZEDER GáborJan 12, 2021
  135. Ævar Arnfjörð BjarmasonJan 20, 2021
  136. SZEDER GáborJan 20, 2021
  137. Ævar Arnfjörð BjarmasonJan 27, 2021
  138. SZEDER GáborFeb 1, 2021
  139. Ævar Arnfjörð BjarmasonFeb 3, 2021
  140. SZEDER GáborFeb 3, 2021
  141. 3/6 tests: remove misc use of test_i18n{cmp,grep}Ævar Arnfjörð Bjarmason, Jan 11, 2021
  142. 6/6 tests: remove uses of GIT_TEST_GETTEXT_POISON=falseÆvar Arnfjörð Bjarmason, Jan 11, 2021
  143. 4/6 tests: (almost) remove use of "test_i18ngrep !"Ævar Arnfjörð Bjarmason, Jan 11, 2021
  144. 5/6 tests: (almost) remove C_LOCALE_OUTPUT prerequisitesÆvar Arnfjörð Bjarmason, Jan 11, 2021
  145. Junio C HamanoJan 11, 2021
  146. Jeff KingJan 12, 2021
  147. SZEDER GáborJan 20, 2021
  148. 09/23 mktag tests: run "fsck" after creating "mytag"Ævar Arnfjörð Bjarmason, Jan 5, 2021
  149. 10/23 mktag tests: stress test whitespace handlingÆvar Arnfjörð Bjarmason, Jan 5, 2021
  150. 14/23 mktag: use default strbuf_read() hintÆvar Arnfjörð Bjarmason, Jan 5, 2021
  151. 15/23 mktag: remove redundant braces in one-line body "if"Ævar Arnfjörð Bjarmason, Jan 5, 2021
  152. 16/23 mktag: use puts(str) instead of printf("%s\n", str)Ævar Arnfjörð Bjarmason, Jan 5, 2021
  153. 21/23 mktag: convert to parse-optionsÆvar Arnfjörð Bjarmason, Jan 5, 2021
  154. 19/23 mktag: allow turning off fsck.extraHeaderEntryÆvar Arnfjörð Bjarmason, Jan 5, 2021
  155. 23/23 mktag: add a --no-strict optionÆvar Arnfjörð Bjarmason, Jan 5, 2021
  156. Junio C HamanoJan 6, 2021
  157. 23/23 mktag: add a --[no-]strict optionÆvar Arnfjörð Bjarmason, Jan 6, 2021
  158. Junio C HamanoJan 6, 2021
  159. Ævar Arnfjörð BjarmasonJan 7, 2021
  160. 22/23 mktag: mark strings for translationÆvar Arnfjörð Bjarmason, Jan 5, 2021
  161. 20/23 mktag: allow omitting the header/body \n separatorÆvar Arnfjörð Bjarmason, Jan 5, 2021
  162. 17/23 mktag: use fsck instead of custom verify_tag()Ævar Arnfjörð Bjarmason, Jan 5, 2021
  163. 18/23 fsck: make fsck_config() re-usableÆvar Arnfjörð Bjarmason, Jan 5, 2021
  164. 02/20 mktag doc: grammar fix, when exists -> when it existsÆvar Arnfjörð Bjarmason, Dec 23, 2020
  165. 03/20 mktag doc: update to explain why to use thisÆvar Arnfjörð Bjarmason, Dec 23, 2020
  166. Junio C HamanoDec 23, 2020
  167. 05/20 mktag tests: remove needless SHA-1 hardcodingÆvar Arnfjörð Bjarmason, Dec 23, 2020
  168. 04/20 mktag tests: don't needlessly use a subshellÆvar Arnfjörð Bjarmason, Dec 23, 2020
  169. 16/20 mktag: allow turning off fsck.extraHeaderEntryÆvar Arnfjörð Bjarmason, Dec 23, 2020
  170. SZEDER GáborDec 23, 2020
  171. 14/20 mktag: use fsck instead of custom verify_tag()Ævar Arnfjörð Bjarmason, Dec 23, 2020
  172. Junio C HamanoDec 23, 2020
  173. 20/20 mktag: add a --no-strict optionÆvar Arnfjörð Bjarmason, Dec 23, 2020
  174. Junio C HamanoDec 23, 2020
  175. SZEDER GáborDec 23, 2020
  176. 18/20 mktag: convert to parse-optionsÆvar Arnfjörð Bjarmason, Dec 23, 2020
  177. 06/20 mktag tests: improve verify_object() test coverageÆvar Arnfjörð Bjarmason, Dec 23, 2020
  178. Junio C HamanoDec 23, 2020
  179. 11/20 mktag: use default strbuf_read() hintÆvar Arnfjörð Bjarmason, Dec 23, 2020
  180. 07/20 mktag tests: don't pipe to stderr needlesslyÆvar Arnfjörð Bjarmason, Dec 23, 2020
  181. Junio C HamanoDec 23, 2020
  182. 10/20 mktag tests: test "hash-object" compatibilityÆvar Arnfjörð Bjarmason, Dec 23, 2020
  183. Junio C HamanoDec 23, 2020
  184. 13/20 mktag: use puts(str) instead of printf("%s\n", str)Ævar Arnfjörð Bjarmason, Dec 23, 2020
  185. 17/20 mktag: allow omitting the header/body \n separatorÆvar Arnfjörð Bjarmason, Dec 23, 2020
  186. 12/20 mktag: remove redundant braces in one-line body "if"Ævar Arnfjörð Bjarmason, Dec 23, 2020
  187. 15/20 fsck: make fsck_config() re-usableÆvar Arnfjörð Bjarmason, Dec 23, 2020
  188. 09/20 mktag tests: stress test whitespace handlingÆvar Arnfjörð Bjarmason, Dec 23, 2020
  189. Junio C HamanoDec 23, 2020
  190. 08/20 mktag tests: don't create "mytag" twiceÆvar Arnfjörð Bjarmason, Dec 23, 2020
  191. Junio C HamanoDec 23, 2020
  192. 19/20 mktag: mark strings for translationÆvar Arnfjörð Bjarmason, Dec 23, 2020
  193. 04/10 mktag tests: don't needlessly use a subshellÆvar Arnfjörð Bjarmason, Dec 9, 2020
  194. 05/10 mktag tests: remove needless SHA-1 hardcodingÆvar Arnfjörð Bjarmason, Dec 9, 2020
  195. 05/10 mktag tests: don't needlessly use a subshellÆvar Arnfjörð Bjarmason, Nov 26, 2020
  196. 01/10 mktag doc: say <hash> not <sha1>Ævar Arnfjörð Bjarmason, Nov 26, 2020
  197. Junio C HamanoDec 1, 2020
  198. 07/10 mktag tests: improve verify_object() test coverageÆvar Arnfjörð Bjarmason, Nov 26, 2020
  199. 10/10 mktag doc: update to explain why to use thisÆvar Arnfjörð Bjarmason, Nov 26, 2020
  200. Junio C HamanoDec 1, 2020
  201. 06/10 mktag tests: remove needless SHA-1 hardcodingÆvar Arnfjörð Bjarmason, Nov 26, 2020
  202. Junio C HamanoDec 1, 2020
  203. 09/10 mktag: use fsck instead of custom verify_tag()Ævar Arnfjörð Bjarmason, Nov 26, 2020
  204. Junio C HamanoDec 1, 2020
  205. Junio C HamanoDec 1, 2020
  206. 08/10 fsck: add new "extra" checks for "mktag"Ævar Arnfjörð Bjarmason, Nov 26, 2020
  207. Junio C HamanoDec 1, 2020
  208. 02/12 mktag: reword write_object_file() errorÆvar Arnfjörð Bjarmason, Nov 26, 2020
  209. 03/12 mktag: remove redundant braces in one-line body "if"Ævar Arnfjörð Bjarmason, Nov 26, 2020
  210. 06/12 mktag tests: improve verify_object() test coverageÆvar Arnfjörð Bjarmason, Nov 26, 2020
  211. 04/12 mktag tests: don't needlessly use a subshellÆvar Arnfjörð Bjarmason, Nov 26, 2020
  212. 05/12 mktag tests: remove needless SHA-1 hardcodingÆvar Arnfjörð Bjarmason, Nov 26, 2020
  213. Jeff KingNov 26, 2020
  214. 08/12 mktag: use fsck instead of custom verify_tag()Ævar Arnfjörð Bjarmason, Nov 26, 2020
  215. Jeff KingNov 26, 2020
  216. Ævar Arnfjörð BjarmasonNov 26, 2020
  217. 07/12 fsck: add new "extra" checks for "mktag"Ævar Arnfjörð Bjarmason, Nov 26, 2020
  218. Jeff KingNov 26, 2020
  219. Ævar Arnfjörð BjarmasonNov 26, 2020
  220. 11/12 mktag docs: say <hash> not <sha1>Ævar Arnfjörð Bjarmason, Nov 26, 2020
  221. 09/12 mktag: remove now-unused verify_tag() codeÆvar Arnfjörð Bjarmason, Nov 26, 2020
  222. Jeff KingNov 26, 2020
  223. 12/12 mktag: bring back some of the verify_object() logicÆvar Arnfjörð Bjarmason, Nov 26, 2020
  224. Jeff KingNov 26, 2020
  225. 10/12 mktag doc: update to explain why to use thisÆvar Arnfjörð Bjarmason, Nov 26, 2020
  226. 11/14 t3903: abstract away SHA-1-specific constantsbrian m. carlson, Aug 26, 2019
  227. 12/14 t4000: make hash size independentbrian m. carlson, Aug 26, 2019
  228. 14/14 t4009: make hash size independentbrian m. carlson, Aug 26, 2019
  229. 13/14 t4002: make hash independentbrian m. carlson, Aug 26, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.