mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 12:24:11 +00:00
signature: straighten the creation of a signature
- Fails on empty name and/or email - Trims leading and trailing spaces of name and email
This commit is contained in:
parent
42a1b5e1ad
commit
a01acc47bb
110
src/signature.c
110
src/signature.c
@ -33,26 +33,84 @@ void git_signature_free(git_signature *sig)
|
||||
if (sig == NULL)
|
||||
return;
|
||||
|
||||
free(sig->name);
|
||||
free(sig->email);
|
||||
if (sig->name)
|
||||
free(sig->name);
|
||||
|
||||
if (sig->email)
|
||||
free(sig->email);
|
||||
|
||||
free(sig);
|
||||
}
|
||||
|
||||
static const char *skip_leading_spaces(const char *buffer, const char *buffer_end)
|
||||
{
|
||||
while (*buffer == ' ' && buffer < buffer_end)
|
||||
buffer++;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static const char *skip_trailing_spaces(const char *buffer_start, const char *buffer_end)
|
||||
{
|
||||
while (*buffer_end == ' ' && buffer_end > buffer_start)
|
||||
buffer_end--;
|
||||
|
||||
return buffer_end;
|
||||
}
|
||||
|
||||
static int process_trimming(const char *input, char **storage, const char *input_end, int fail_when_empty)
|
||||
{
|
||||
const char *left, *right;
|
||||
int trimmed_input_length;
|
||||
|
||||
left = skip_leading_spaces(input, input_end);
|
||||
right = skip_trailing_spaces(input, input_end - 1);
|
||||
|
||||
if (right <= left)
|
||||
if (fail_when_empty)
|
||||
return git__throw(GIT_EINVALIDARGS, "Failed to trim. Input is either empty or only contains spaces");
|
||||
else
|
||||
right = left - 1;
|
||||
|
||||
trimmed_input_length = right - left + 1;
|
||||
|
||||
*storage = git__malloc(trimmed_input_length + 1);
|
||||
if (*storage == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
memcpy(*storage, left, trimmed_input_length);
|
||||
(*storage)[trimmed_input_length] = 0;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
git_signature *git_signature_new(const char *name, const char *email, git_time_t time, int offset)
|
||||
{
|
||||
int error;
|
||||
git_signature *p = NULL;
|
||||
|
||||
assert(name && email);
|
||||
|
||||
if ((p = git__malloc(sizeof(git_signature))) == NULL)
|
||||
goto cleanup;
|
||||
|
||||
p->name = git__strdup(name);
|
||||
p->email = git__strdup(email);
|
||||
memset(p, 0x0, sizeof(git_signature));
|
||||
|
||||
error = process_trimming(name, &p->name, name + strlen(name), 1);
|
||||
if (error < GIT_SUCCESS) {
|
||||
git__rethrow(GIT_EINVALIDARGS, "Failed to create signature. 'name' argument is invalid");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
error = process_trimming(email, &p->email, email + strlen(email), 1);
|
||||
if (error < GIT_SUCCESS) {
|
||||
git__rethrow(GIT_EINVALIDARGS, "Failed to create signature. 'email' argument is invalid");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
p->when.time = time;
|
||||
p->when.offset = offset;
|
||||
|
||||
if (p->name == NULL || p->email == NULL)
|
||||
goto cleanup;
|
||||
|
||||
return p;
|
||||
|
||||
cleanup:
|
||||
@ -149,46 +207,28 @@ static int parse_timezone_offset(const char *buffer, int *offset_out)
|
||||
}
|
||||
|
||||
int process_next_token(const char **buffer_out, char **storage,
|
||||
const char *token_end, const char *line_end)
|
||||
const char *token_end, const char *right_boundary)
|
||||
{
|
||||
int name_length = 0;
|
||||
const char *buffer = *buffer_out;
|
||||
int error = process_trimming(*buffer_out, storage, token_end, 0);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
/* Skip leading spaces before the name */
|
||||
while (*buffer == ' ' && buffer < line_end)
|
||||
buffer++;
|
||||
*buffer_out = token_end + 1;
|
||||
|
||||
name_length = token_end - buffer;
|
||||
|
||||
/* Trim trailing spaces after the name */
|
||||
while (buffer[name_length - 1] == ' ' && name_length > 0)
|
||||
name_length--;
|
||||
|
||||
*storage = git__malloc(name_length + 1);
|
||||
if (*storage == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
memcpy(*storage, buffer, name_length);
|
||||
(*storage)[name_length] = 0;
|
||||
buffer = token_end + 1;
|
||||
|
||||
if (buffer > line_end)
|
||||
if (*buffer_out > right_boundary)
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
|
||||
|
||||
*buffer_out = buffer;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
const char* scan_for_previous_token(const char *buffer, const char *left_boundary)
|
||||
const char *scan_for_previous_token(const char *buffer, const char *left_boundary)
|
||||
{
|
||||
const char *start = buffer;
|
||||
const char *start;
|
||||
|
||||
if (start <= left_boundary)
|
||||
if (buffer <= left_boundary)
|
||||
return NULL;
|
||||
|
||||
/* Trim potential trailing spaces */
|
||||
while (*start == ' ' && start > left_boundary)
|
||||
start--;
|
||||
start = skip_trailing_spaces(left_boundary, buffer);
|
||||
|
||||
/* Search for previous occurence of space */
|
||||
while (start[-1] != ' ' && start > left_boundary)
|
||||
|
@ -331,7 +331,6 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
|
||||
123456,
|
||||
-60);
|
||||
|
||||
|
||||
/* Parse an obviously invalid signature */
|
||||
TEST_SIGNATURE_PASS(
|
||||
"committer <>\n",
|
||||
@ -446,6 +445,39 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
|
||||
|
||||
END_TEST
|
||||
|
||||
static int try_build_signature(const char *name, const char *email, git_time_t time, int offset)
|
||||
{
|
||||
git_signature *sign;
|
||||
int error = GIT_SUCCESS;
|
||||
|
||||
sign = git_signature_new(name, email, time, offset);
|
||||
|
||||
if (sign == NULL)
|
||||
error = GIT_ERROR;
|
||||
|
||||
git_signature_free((git_signature *)sign);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
BEGIN_TEST(signature0, "creating a signature trims leading and trailing spaces")
|
||||
git_signature *sign;
|
||||
sign = git_signature_new(" nulltoken ", " emeric.fermas@gmail.com ", 1234567890, 60);
|
||||
must_be_true(sign != NULL);
|
||||
must_pass(strcmp(sign->name, "nulltoken"));
|
||||
must_pass(strcmp(sign->email, "emeric.fermas@gmail.com"));
|
||||
git_signature_free((git_signature *)sign);
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(signature1, "can not create a signature with empty name or email")
|
||||
must_pass(try_build_signature("nulltoken", "emeric.fermas@gmail.com", 1234567890, 60));
|
||||
|
||||
must_fail(try_build_signature("", "emeric.fermas@gmail.com", 1234567890, 60));
|
||||
must_fail(try_build_signature(" ", "emeric.fermas@gmail.com", 1234567890, 60));
|
||||
must_fail(try_build_signature("nulltoken", "", 1234567890, 60));
|
||||
must_fail(try_build_signature("nulltoken", " ", 1234567890, 60));
|
||||
END_TEST
|
||||
|
||||
/* External declaration for testing the buffer parsing method */
|
||||
int commit_parse_buffer(git_commit *commit, void *data, size_t len, unsigned int parse_flags);
|
||||
|
||||
@ -722,4 +754,7 @@ BEGIN_SUITE(commit)
|
||||
ADD_TEST(write0);
|
||||
|
||||
ADD_TEST(root0);
|
||||
|
||||
ADD_TEST(signature0);
|
||||
ADD_TEST(signature1);
|
||||
END_SUITE
|
||||
|
Loading…
Reference in New Issue
Block a user