Skip to content

Commit 102192a

Browse files
shejialuogitster
authored andcommitted
ref: add more strict checks for regular refs
We have already used "parse_loose_ref_contents" function to check whether the ref content is valid in files backend. However, by using "parse_loose_ref_contents", we allow the ref's content to end with garbage or without a newline. Even though we never create such loose refs ourselves, we have accepted such loose refs. So, it is entirely possible that some third-party tools may rely on such loose refs being valid. We should not report an error fsck message at current. We should notify the users about such "curiously formatted" loose refs so that adequate care is taken before we decide to tighten the rules in the future. And it's not suitable either to report a warn fsck message to the user. We don't yet want the "--strict" flag that controls this bit to end up generating errors for such weirdly-formatted reference contents, as we first want to assess whether this retroactive tightening will cause issues for any tools out there. It may cause compatibility issues which may break the repository. So we add the following two fsck infos to represent the situation where the ref content ends without newline or has trailing garbages: 1. refMissingNewline(INFO): A ref does not end with newline. This will be considered an error in the future. 2. trailingRefContent(INFO): A ref has trailing content. This will be considered an error in the future. It might appear that we can't provide the user with any warnings by using FSCK_INFO. However, in "fsck.c::fsck_vreport", we will convert FSCK_INFO to FSCK_WARN and we can still warn the user about these situations when using "git refs verify" without introducing compatibility issues. Mentored-by: Patrick Steinhardt <[email protected]> Mentored-by: Karthik Nayak <[email protected]> Signed-off-by: shejialuo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4dad6aa commit 102192a

File tree

6 files changed

+96
-5
lines changed

6 files changed

+96
-5
lines changed

Documentation/fsck-msgids.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@
173173
`nullSha1`::
174174
(WARN) Tree contains entries pointing to a null sha1.
175175

176+
`refMissingNewline`::
177+
(INFO) A ref does not end with newline. This will be
178+
considered an error in the future.
179+
180+
`trailingRefContent`::
181+
(INFO) A ref has trailing content. This will be
182+
considered an error in the future.
183+
176184
`treeNotSorted`::
177185
(ERROR) A tree is not properly sorted.
178186

fsck.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ enum fsck_msg_type {
8585
FUNC(MAILMAP_SYMLINK, INFO) \
8686
FUNC(BAD_TAG_NAME, INFO) \
8787
FUNC(MISSING_TAGGER_ENTRY, INFO) \
88+
FUNC(REF_MISSING_NEWLINE, INFO) \
89+
FUNC(TRAILING_REF_CONTENT, INFO) \
8890
/* ignored (elevated when requested) */ \
8991
FUNC(EXTRA_HEADER_ENTRY, IGNORE)
9092

refs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1758,7 +1758,7 @@ static int refs_read_special_head(struct ref_store *ref_store,
17581758
}
17591759

17601760
result = parse_loose_ref_contents(ref_store->repo->hash_algo, content.buf,
1761-
oid, referent, type, failure_errno);
1761+
oid, referent, type, NULL, failure_errno);
17621762

17631763
done:
17641764
strbuf_release(&full_path);

refs/files-backend.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ static int read_ref_internal(struct ref_store *ref_store, const char *refname,
560560
buf = sb_contents.buf;
561561

562562
ret = parse_loose_ref_contents(ref_store->repo->hash_algo, buf,
563-
oid, referent, type, &myerr);
563+
oid, referent, type, NULL, &myerr);
564564

565565
out:
566566
if (ret && !myerr)
@@ -597,7 +597,7 @@ static int files_read_symbolic_ref(struct ref_store *ref_store, const char *refn
597597
int parse_loose_ref_contents(const struct git_hash_algo *algop,
598598
const char *buf, struct object_id *oid,
599599
struct strbuf *referent, unsigned int *type,
600-
int *failure_errno)
600+
const char **trailing, int *failure_errno)
601601
{
602602
const char *p;
603603
if (skip_prefix(buf, "ref:", &buf)) {
@@ -619,6 +619,10 @@ int parse_loose_ref_contents(const struct git_hash_algo *algop,
619619
*failure_errno = EINVAL;
620620
return -1;
621621
}
622+
623+
if (trailing)
624+
*trailing = p;
625+
622626
return 0;
623627
}
624628

@@ -3439,6 +3443,7 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
34393443
struct strbuf referent = STRBUF_INIT;
34403444
struct strbuf refname = STRBUF_INIT;
34413445
struct fsck_ref_report report = {0};
3446+
const char *trailing = NULL;
34423447
unsigned int type = 0;
34433448
int failure_errno = 0;
34443449
struct object_id oid;
@@ -3458,13 +3463,29 @@ static int files_fsck_refs_content(struct ref_store *ref_store,
34583463

34593464
if (parse_loose_ref_contents(ref_store->repo->hash_algo,
34603465
ref_content.buf, &oid, &referent,
3461-
&type, &failure_errno)) {
3466+
&type, &trailing, &failure_errno)) {
34623467
ret = fsck_report_ref(o, &report,
34633468
FSCK_MSG_BAD_REF_CONTENT,
34643469
"invalid ref content");
34653470
goto cleanup;
34663471
}
34673472

3473+
if (!(type & REF_ISSYMREF)) {
3474+
if (!*trailing) {
3475+
ret = fsck_report_ref(o, &report,
3476+
FSCK_MSG_REF_MISSING_NEWLINE,
3477+
"missing newline");
3478+
goto cleanup;
3479+
}
3480+
3481+
if (*trailing != '\n' || *(trailing + 1)) {
3482+
ret = fsck_report_ref(o, &report,
3483+
FSCK_MSG_TRAILING_REF_CONTENT,
3484+
"trailing garbage in ref");
3485+
goto cleanup;
3486+
}
3487+
}
3488+
34683489
cleanup:
34693490
strbuf_release(&refname);
34703491
strbuf_release(&ref_content);

refs/refs-internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ struct ref_store {
715715
int parse_loose_ref_contents(const struct git_hash_algo *algop,
716716
const char *buf, struct object_id *oid,
717717
struct strbuf *referent, unsigned int *type,
718-
int *failure_errno);
718+
const char **trailing, int *failure_errno);
719719

720720
/*
721721
* Fill in the generic part of refs and add it to our collection of

t/t0602-reffiles-fsck.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,54 @@ test_expect_success 'regular ref content should be checked (individual)' '
101101
git refs verify 2>err &&
102102
test_must_be_empty err &&
103103
104+
printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline &&
105+
git refs verify 2>err &&
106+
cat >expect <<-EOF &&
107+
warning: refs/heads/branch-no-newline: refMissingNewline: missing newline
108+
EOF
109+
rm $branch_dir_prefix/branch-no-newline &&
110+
test_cmp expect err &&
111+
112+
printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage &&
113+
git refs verify 2>err &&
114+
cat >expect <<-EOF &&
115+
warning: refs/heads/branch-garbage: trailingRefContent: trailing garbage in ref
116+
EOF
117+
rm $branch_dir_prefix/branch-garbage &&
118+
test_cmp expect err &&
119+
120+
printf "%s\n\n\n" "$(git rev-parse main)" >$tag_dir_prefix/tag-garbage-1 &&
121+
git refs verify 2>err &&
122+
cat >expect <<-EOF &&
123+
warning: refs/tags/tag-garbage-1: trailingRefContent: trailing garbage in ref
124+
EOF
125+
rm $tag_dir_prefix/tag-garbage-1 &&
126+
test_cmp expect err &&
127+
128+
printf "%s\n\n\n garbage" "$(git rev-parse main)" >$tag_dir_prefix/tag-garbage-2 &&
129+
git refs verify 2>err &&
130+
cat >expect <<-EOF &&
131+
warning: refs/tags/tag-garbage-2: trailingRefContent: trailing garbage in ref
132+
EOF
133+
rm $tag_dir_prefix/tag-garbage-2 &&
134+
test_cmp expect err &&
135+
136+
printf "%s garbage\n\na" "$(git rev-parse main)" >$tag_dir_prefix/tag-garbage-3 &&
137+
git refs verify 2>err &&
138+
cat >expect <<-EOF &&
139+
warning: refs/tags/tag-garbage-3: trailingRefContent: trailing garbage in ref
140+
EOF
141+
rm $tag_dir_prefix/tag-garbage-3 &&
142+
test_cmp expect err &&
143+
144+
printf "%s garbage" "$(git rev-parse main)" >$tag_dir_prefix/tag-garbage-4 &&
145+
test_must_fail git -c fsck.trailingRefContent=error refs verify 2>err &&
146+
cat >expect <<-EOF &&
147+
error: refs/tags/tag-garbage-4: trailingRefContent: trailing garbage in ref
148+
EOF
149+
rm $tag_dir_prefix/tag-garbage-4 &&
150+
test_cmp expect err &&
151+
104152
printf "%sx" "$(git rev-parse main)" >$tag_dir_prefix/tag-bad-1 &&
105153
test_must_fail git refs verify 2>err &&
106154
cat >expect <<-EOF &&
@@ -135,6 +183,12 @@ test_expect_success 'regular ref content should be checked (aggregate)' '
135183
test_commit default &&
136184
mkdir -p "$branch_dir_prefix/a/b" &&
137185
186+
printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline &&
187+
printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage &&
188+
printf "%s\n\n\n" "$(git rev-parse main)" >$tag_dir_prefix/tag-garbage-1 &&
189+
printf "%s\n\n\n garbage" "$(git rev-parse main)" >$tag_dir_prefix/tag-garbage-2 &&
190+
printf "%s garbage\n\na" "$(git rev-parse main)" >$tag_dir_prefix/tag-garbage-3 &&
191+
printf "%s garbage" "$(git rev-parse main)" >$tag_dir_prefix/tag-garbage-4 &&
138192
printf "%sx" "$(git rev-parse main)" >$tag_dir_prefix/tag-bad-1 &&
139193
printf "xfsazqfxcadas" >$tag_dir_prefix/tag-bad-2 &&
140194
printf "xfsazqfxcadas" >$branch_dir_prefix/a/b/branch-bad &&
@@ -144,6 +198,12 @@ test_expect_success 'regular ref content should be checked (aggregate)' '
144198
error: refs/heads/a/b/branch-bad: badRefContent: invalid ref content
145199
error: refs/tags/tag-bad-1: badRefContent: invalid ref content
146200
error: refs/tags/tag-bad-2: badRefContent: invalid ref content
201+
warning: refs/heads/branch-garbage: trailingRefContent: trailing garbage in ref
202+
warning: refs/heads/branch-no-newline: refMissingNewline: missing newline
203+
warning: refs/tags/tag-garbage-1: trailingRefContent: trailing garbage in ref
204+
warning: refs/tags/tag-garbage-2: trailingRefContent: trailing garbage in ref
205+
warning: refs/tags/tag-garbage-3: trailingRefContent: trailing garbage in ref
206+
warning: refs/tags/tag-garbage-4: trailingRefContent: trailing garbage in ref
147207
EOF
148208
sort err >sorted_err &&
149209
test_cmp expect sorted_err

0 commit comments

Comments
 (0)