Commit f063dafb by Henry Kleynhans

signature: distinguish +0000 and -0000 UTC offsets

Git considers '-0000' a valid offset for signature lines.  They need to
be treated as _not_ equal to a '+0000' signature offset.  Parsing a
signature line stores the offset in a signed integer which does not
distinguish between `+0` and `-0`.

This patch adds an additional flag `sign` to the `git_time` in the
`signature` object which is populated with the sign of the offset.  In
addition to exposing this information to the user, this information is
also used to compare signatures.

/cc @pks-t @ethomson
parent 1d7c15ad
...@@ -159,6 +159,7 @@ typedef struct git_packbuilder git_packbuilder; ...@@ -159,6 +159,7 @@ typedef struct git_packbuilder git_packbuilder;
typedef struct git_time { typedef struct git_time {
git_time_t time; /**< time in seconds from epoch */ git_time_t time; /**< time in seconds from epoch */
int offset; /**< timezone offset, in minutes */ int offset; /**< timezone offset, in minutes */
char sign; /**< indicator for questionable '-0000' offsets in signature */
} git_time; } git_time;
/** An action signature (e.g. for committers, taggers, etc) */ /** An action signature (e.g. for committers, taggers, etc) */
......
...@@ -90,6 +90,7 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema ...@@ -90,6 +90,7 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema
p->when.time = time; p->when.time = time;
p->when.offset = offset; p->when.offset = offset;
p->when.sign = (offset < 0) ? '-' : '+';
*sig_out = p; *sig_out = p;
return 0; return 0;
...@@ -113,6 +114,7 @@ int git_signature_dup(git_signature **dest, const git_signature *source) ...@@ -113,6 +114,7 @@ int git_signature_dup(git_signature **dest, const git_signature *source)
signature->when.time = source->when.time; signature->when.time = source->when.time;
signature->when.offset = source->when.offset; signature->when.offset = source->when.offset;
signature->when.sign = source->when.sign;
*dest = signature; *dest = signature;
...@@ -137,6 +139,7 @@ int git_signature__pdup(git_signature **dest, const git_signature *source, git_p ...@@ -137,6 +139,7 @@ int git_signature__pdup(git_signature **dest, const git_signature *source, git_p
signature->when.time = source->when.time; signature->when.time = source->when.time;
signature->when.offset = source->when.offset; signature->when.offset = source->when.offset;
signature->when.sign = source->when.sign;
*dest = signature; *dest = signature;
...@@ -257,6 +260,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out, ...@@ -257,6 +260,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
*/ */
if (hours <= 14 && mins <= 59) { if (hours <= 14 && mins <= 59) {
sig->when.offset = (hours * 60) + mins; sig->when.offset = (hours * 60) + mins;
sig->when.sign = tz_start[0];
if (tz_start[0] == '-') if (tz_start[0] == '-')
sig->when.offset = -sig->when.offset; sig->when.offset = -sig->when.offset;
} }
...@@ -299,7 +303,7 @@ void git_signature__writebuf(git_buf *buf, const char *header, const git_signatu ...@@ -299,7 +303,7 @@ void git_signature__writebuf(git_buf *buf, const char *header, const git_signatu
assert(buf && sig); assert(buf && sig);
offset = sig->when.offset; offset = sig->when.offset;
sign = (sig->when.offset < 0) ? '-' : '+'; sign = (sig->when.offset < 0 || sig->when.sign == '-') ? '-' : '+';
if (offset < 0) if (offset < 0)
offset = -offset; offset = -offset;
...@@ -320,6 +324,7 @@ bool git_signature__equal(const git_signature *one, const git_signature *two) ...@@ -320,6 +324,7 @@ bool git_signature__equal(const git_signature *one, const git_signature *two)
git__strcmp(one->name, two->name) == 0 && git__strcmp(one->name, two->name) == 0 &&
git__strcmp(one->email, two->email) == 0 && git__strcmp(one->email, two->email) == 0 &&
one->when.time == two->when.time && one->when.time == two->when.time &&
one->when.offset == two->when.offset; one->when.offset == two->when.offset &&
one->when.sign == two->when.sign;
} }
#include "clar_libgit2.h" #include "clar_libgit2.h"
#include "signature.h"
static int try_build_signature(const char *name, const char *email, git_time_t time, int offset) static int try_build_signature(const char *name, const char *email, git_time_t time, int offset)
{ {
...@@ -99,3 +100,29 @@ void test_commit_signature__from_buf(void) ...@@ -99,3 +100,29 @@ void test_commit_signature__from_buf(void)
git_signature_free(sign); git_signature_free(sign);
} }
void test_commit_signature__from_buf_with_neg_zero_offset(void)
{
git_signature *sign;
cl_git_pass(git_signature_from_buffer(&sign, "Test User <test@test.tt> 1461698487 -0000"));
cl_assert_equal_s("Test User", sign->name);
cl_assert_equal_s("test@test.tt", sign->email);
cl_assert_equal_i(1461698487, sign->when.time);
cl_assert_equal_i(0, sign->when.offset);
cl_assert_equal_i('-', sign->when.sign);
git_signature_free(sign);
}
void test_commit_signature__pos_and_neg_zero_offsets_dont_match(void)
{
git_signature *with_neg_zero;
git_signature *with_pos_zero;
cl_git_pass(git_signature_from_buffer(&with_neg_zero, "Test User <test@test.tt> 1461698487 -0000"));
cl_git_pass(git_signature_from_buffer(&with_pos_zero, "Test User <test@test.tt> 1461698487 +0000"));
cl_assert(!git_signature__equal(with_neg_zero, with_pos_zero));
git_signature_free((git_signature *)with_neg_zero);
git_signature_free((git_signature *)with_pos_zero);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment