git_signature__parse: make parsing less strict git_signature__parse used to be very strict about what's a well-formed signature. Since git_signature__parse is used only when reading already existing signatures, we should not care about if it's a valid signature too much but rather show what we got. Reported-by: nulltoken <emeric.fermas@gmail.com> Signed-off-by: schu <schu-github@schulog.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
diff --git a/src/signature.c b/src/signature.c
index 7d23336..38bd7d7 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -153,8 +153,6 @@ static int parse_timezone_offset(const char *buffer, long *offset_out)
int git_signature__parse(git_signature *sig, const char **buffer_out,
const char *buffer_end, const char *header)
{
- const size_t header_len = strlen(header);
-
int name_length, email_length;
const char *buffer = *buffer_out;
const char *line_end, *name_end, *email_end;
@@ -162,38 +160,40 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
memset(sig, 0x0, sizeof(git_signature));
- line_end = memchr(buffer, '\n', buffer_end - buffer);
- if (!line_end)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. No newline found");;
+ if ((line_end = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. No newline given");
- if (buffer + (header_len + 1) > line_end)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
+ if (header) {
+ const size_t header_len = strlen(header);
- if (memcmp(buffer, header, header_len) != 0)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Expected prefix '%s' doesn't match actual", header);
+ if (memcmp(buffer, header, header_len) != 0)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Expected prefix '%s' doesn't match actual", header);
- buffer += header_len;
+ buffer += header_len;
+ }
- /* Parse name */
- if ((name_end = strstr(buffer, " <")) == NULL)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail start");
+ if (buffer > line_end)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
- name_length = name_end - buffer;
+ if ((name_end = strchr(buffer, '<')) == NULL)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Cannot find '<' in signature");
+ name_length = name_end - 1 - buffer;
+ if (name_length < 0)
+ name_length = 0;
sig->name = git__malloc(name_length + 1);
if (sig->name == NULL)
return GIT_ENOMEM;
memcpy(sig->name, buffer, name_length);
sig->name[name_length] = 0;
- buffer = name_end + 2;
+ buffer = name_end + 1;
- if (buffer >= line_end)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly");
+ if (buffer > line_end)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
- /* Parse email */
- if ((email_end = strstr(buffer, "> ")) == NULL)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail end");
+ if ((email_end = strchr(buffer, '>')) == NULL)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Cannot find '>' in signature");
email_length = email_end - buffer;
sig->email = git__malloc(email_length + 1);
@@ -204,10 +204,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
sig->email[email_length] = 0;
buffer = email_end + 2;
- if (buffer >= line_end)
- return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly");
+ if (buffer > line_end)
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
- /* verify email */
if (strpbrk(sig->email, "><\n") != NULL)
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Malformed e-mail");
@@ -221,7 +220,8 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
sig->when.offset = offset;
- *buffer_out = (line_end + 1);
+ *buffer_out = line_end + 1;
+
return GIT_SUCCESS;
}