Skip to content

Commit 830424d

Browse files
peffgitster
authored andcommitted
fsck: avoid strcspn() in fsck_ident()
We may be operating on a buffer that is not NUL-terminated, but we use strcspn() to parse it. This is OK in practice, as discussed in 8e43090 (fsck: do not assume NUL-termination of buffers, 2023-01-19), because we know there is at least a trailing newline in our buffer, and we always pass "\n" to strcspn(). So we know it will stop before running off the end of the buffer. But this is a subtle point to hang our memory safety hat on. And it confuses ASan's strict_string_checks mode, even though it is technically a false positive (that mode complains that we have no NUL, which is true, but it does not know that we have verified the presence of the newline already). Let's instead open-code the loop. As a bonus, this makes the logic more obvious (to my mind, anyway). The current code skips forward with strcspn until it hits "<", ">", or "\n". But then it must check which it saw to decide if that was what we expected or not, duplicating some logic between what's in the strcspn() and what's in the domain logic. Instead, we can just check each character as we loop and act on it immediately. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0b6ec07 commit 830424d

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

fsck.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -874,18 +874,30 @@ static int fsck_ident(const char **ident, const char *ident_end,
874874

875875
if (*p == '<')
876876
return report(options, oid, type, FSCK_MSG_MISSING_NAME_BEFORE_EMAIL, "invalid author/committer line - missing space before email");
877-
p += strcspn(p, "<>\n");
878-
if (*p == '>')
879-
return report(options, oid, type, FSCK_MSG_BAD_NAME, "invalid author/committer line - bad name");
880-
if (*p != '<')
881-
return report(options, oid, type, FSCK_MSG_MISSING_EMAIL, "invalid author/committer line - missing email");
877+
for (;;) {
878+
if (p >= ident_end || *p == '\n')
879+
return report(options, oid, type, FSCK_MSG_MISSING_EMAIL, "invalid author/committer line - missing email");
880+
if (*p == '>')
881+
return report(options, oid, type, FSCK_MSG_BAD_NAME, "invalid author/committer line - bad name");
882+
if (*p == '<')
883+
break; /* end of name, beginning of email */
884+
885+
/* otherwise, skip past arbitrary name char */
886+
p++;
887+
}
882888
if (p[-1] != ' ')
883889
return report(options, oid, type, FSCK_MSG_MISSING_SPACE_BEFORE_EMAIL, "invalid author/committer line - missing space before email");
884-
p++;
885-
p += strcspn(p, "<>\n");
886-
if (*p != '>')
887-
return report(options, oid, type, FSCK_MSG_BAD_EMAIL, "invalid author/committer line - bad email");
888-
p++;
890+
p++; /* skip past '<' we found */
891+
for (;;) {
892+
if (p >= ident_end || *p == '<' || *p == '\n')
893+
return report(options, oid, type, FSCK_MSG_BAD_EMAIL, "invalid author/committer line - bad email");
894+
if (*p == '>')
895+
break; /* end of email */
896+
897+
/* otherwise, skip past arbitrary email char */
898+
p++;
899+
}
900+
p++; /* skip past '>' we found */
889901
if (*p != ' ')
890902
return report(options, oid, type, FSCK_MSG_MISSING_SPACE_BEFORE_DATE, "invalid author/committer line - missing space before date");
891903
p++;

0 commit comments

Comments
 (0)