From 4e53c28096f4b04ab9b573fc594a538f51e10049 Mon Sep 17 00:00:00 2001 From: Jacques Germishuys Date: Sun, 17 Aug 2014 14:55:06 +0200 Subject: [PATCH 1/2] Check if the refspec matches before transforming --- src/refspec.c | 16 ++++++++++++-- tests/network/refspecs.c | 48 +++++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/refspec.c b/src/refspec.c index 77c58c84e..8689769f3 100644 --- a/src/refspec.c +++ b/src/refspec.c @@ -223,21 +223,33 @@ static int refspec_transform( int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *name) { - git_buf_sanitize(out); + assert(out && spec && name); + git_buf_sanitize(out); if (!spec->pattern) return git_buf_puts(out, spec->dst); + if (!git_refspec_src_matches(spec, name)) { + giterr_set(GITERR_INVALID, "ref '%s' doesn't match the source", name); + return -1; + } + return refspec_transform(out, spec->src, spec->dst, name); } int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *name) { - git_buf_sanitize(out); + assert(out && spec && name); + git_buf_sanitize(out); if (!spec->pattern) return git_buf_puts(out, spec->src); + if (!git_refspec_dst_matches(spec, name)) { + giterr_set(GITERR_INVALID, "ref '%s' doesn't match the destination", name); + return -1; + } + return refspec_transform(out, spec->dst, spec->src, name); } diff --git a/tests/network/refspecs.c b/tests/network/refspecs.c index aa9b36e58..c6bcb10e8 100644 --- a/tests/network/refspecs.c +++ b/tests/network/refspecs.c @@ -88,7 +88,7 @@ void test_network_refspecs__parsing(void) assert_refspec(GIT_DIRECTION_FETCH, "refs/pull/*/head:refs/remotes/origin/pr/*", true); } -void assert_transform(const char *refspec, const char *name, const char *result) +static void assert_valid_transform(const char *refspec, const char *name, const char *result) { git_refspec spec; git_buf buf = GIT_BUF_INIT; @@ -103,8 +103,46 @@ void assert_transform(const char *refspec, const char *name, const char *result) void test_network_refspecs__transform_mid_star(void) { - assert_transform("refs/pull/*/head:refs/remotes/origin/pr/*", "refs/pull/23/head", "refs/remotes/origin/pr/23"); - assert_transform("refs/heads/*:refs/remotes/origin/*", "refs/heads/master", "refs/remotes/origin/master"); - assert_transform("refs/heads/*:refs/heads/*", "refs/heads/master", "refs/heads/master"); - assert_transform("refs/*:refs/*", "refs/heads/master", "refs/heads/master"); + assert_valid_transform("refs/pull/*/head:refs/remotes/origin/pr/*", "refs/pull/23/head", "refs/remotes/origin/pr/23"); + assert_valid_transform("refs/heads/*:refs/remotes/origin/*", "refs/heads/master", "refs/remotes/origin/master"); + assert_valid_transform("refs/heads/*:refs/remotes/origin/*", "refs/heads/user/feature", "refs/remotes/origin/user/feature"); + assert_valid_transform("refs/heads/*:refs/heads/*", "refs/heads/master", "refs/heads/master"); + assert_valid_transform("refs/heads/*:refs/heads/*", "refs/heads/user/feature", "refs/heads/user/feature"); + assert_valid_transform("refs/*:refs/*", "refs/heads/master", "refs/heads/master"); +} + +static void assert_invalid_transform(const char *refspec, const char *name) +{ + git_refspec spec; + git_buf buf = GIT_BUF_INIT; + + git_refspec__parse(&spec, refspec, true); + cl_git_fail(git_refspec_transform(&buf, &spec, name)); + + git_buf_free(&buf); + git_refspec__free(&spec); +} + +void test_network_refspecs__invalid(void) +{ + assert_invalid_transform("refs/heads/*:refs/remotes/origin/*", "master"); + assert_invalid_transform("refs/heads/*:refs/remotes/origin/*", "refs/headz/master"); +} + +static void assert_invalid_rtransform(const char *refspec, const char *name) +{ + git_refspec spec; + git_buf buf = GIT_BUF_INIT; + + git_refspec__parse(&spec, refspec, true); + cl_git_fail(git_refspec_rtransform(&buf, &spec, name)); + + git_buf_free(&buf); + git_refspec__free(&spec); +} + +void test_network_refspecs__invalid_reverse(void) +{ + assert_invalid_rtransform("refs/heads/*:refs/remotes/origin/*", "master"); + assert_invalid_rtransform("refs/heads/*:refs/remotes/origin/*", "refs/remotes/o/master"); } From 8f6073f63e42c2a3ff3b6fbb20729c7a911be30f Mon Sep 17 00:00:00 2001 From: Jacques Germishuys Date: Thu, 21 Aug 2014 18:53:43 +0200 Subject: [PATCH 2/2] Check that the refspec matches before modifying the out buffer --- src/refspec.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/refspec.c b/src/refspec.c index 8689769f3..9f0df35a7 100644 --- a/src/refspec.c +++ b/src/refspec.c @@ -226,14 +226,14 @@ int git_refspec_transform(git_buf *out, const git_refspec *spec, const char *nam assert(out && spec && name); git_buf_sanitize(out); - if (!spec->pattern) - return git_buf_puts(out, spec->dst); - if (!git_refspec_src_matches(spec, name)) { giterr_set(GITERR_INVALID, "ref '%s' doesn't match the source", name); return -1; } + if (!spec->pattern) + return git_buf_puts(out, spec->dst); + return refspec_transform(out, spec->src, spec->dst, name); } @@ -242,14 +242,14 @@ int git_refspec_rtransform(git_buf *out, const git_refspec *spec, const char *na assert(out && spec && name); git_buf_sanitize(out); - if (!spec->pattern) - return git_buf_puts(out, spec->src); - if (!git_refspec_dst_matches(spec, name)) { giterr_set(GITERR_INVALID, "ref '%s' doesn't match the destination", name); return -1; } + if (!spec->pattern) + return git_buf_puts(out, spec->src); + return refspec_transform(out, spec->dst, spec->src, name); }