Commit 8d3b39a6 by Edward Thomson

Merge branch 'pr/3912'

parents 0418d3b7 28d0ba0b
...@@ -175,6 +175,7 @@ typedef enum { ...@@ -175,6 +175,7 @@ typedef enum {
GIT_OPT_SET_SSL_CERT_LOCATIONS, GIT_OPT_SET_SSL_CERT_LOCATIONS,
GIT_OPT_SET_USER_AGENT, GIT_OPT_SET_USER_AGENT,
GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, GIT_OPT_ENABLE_STRICT_OBJECT_CREATION,
GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION,
GIT_OPT_SET_SSL_CIPHERS, GIT_OPT_SET_SSL_CIPHERS,
GIT_OPT_GET_USER_AGENT, GIT_OPT_GET_USER_AGENT,
} git_libgit2_opt_t; } git_libgit2_opt_t;
...@@ -289,6 +290,15 @@ typedef enum { ...@@ -289,6 +290,15 @@ typedef enum {
* > will be validated when creating a new commit. This defaults * > will be validated when creating a new commit. This defaults
* > to enabled. * > to enabled.
* *
* * opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, int enabled)
*
* > Validate the target of a symbolic ref when creating it. For
* > example, `foobar` is not a valid ref, therefore `foobar` is
* > not a valid target for a symbolic ref by default, whereas
* > `refs/heads/foobar` is. Disabling this bypasses validation
* > so that an arbitrary strings such as `foobar` can be used
* > for a symbolic ref target. This defaults to enabled.
*
* * opts(GIT_OPT_SET_SSL_CIPHERS, const char *ciphers) * * opts(GIT_OPT_SET_SSL_CIPHERS, const char *ciphers)
* *
* > Set the SSL ciphers use for HTTPS connections. * > Set the SSL ciphers use for HTTPS connections.
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <git2/signature.h> #include <git2/signature.h>
#include <git2/commit.h> #include <git2/commit.h>
bool git_reference__enable_symbolic_ref_target_validation = true;
GIT__USE_STRMAP GIT__USE_STRMAP
#define DEFAULT_NESTING_LEVEL 5 #define DEFAULT_NESTING_LEVEL 5
...@@ -178,7 +180,8 @@ int git_reference_name_to_id( ...@@ -178,7 +180,8 @@ int git_reference_name_to_id(
static int reference_normalize_for_repo( static int reference_normalize_for_repo(
git_refname_t out, git_refname_t out,
git_repository *repo, git_repository *repo,
const char *name) const char *name,
bool validate)
{ {
int precompose; int precompose;
unsigned int flags = GIT_REF_FORMAT_ALLOW_ONELEVEL; unsigned int flags = GIT_REF_FORMAT_ALLOW_ONELEVEL;
...@@ -187,6 +190,9 @@ static int reference_normalize_for_repo( ...@@ -187,6 +190,9 @@ static int reference_normalize_for_repo(
precompose) precompose)
flags |= GIT_REF_FORMAT__PRECOMPOSE_UNICODE; flags |= GIT_REF_FORMAT__PRECOMPOSE_UNICODE;
if (!validate)
flags |= GIT_REF_FORMAT__VALIDATION_DISABLE;
return git_reference_normalize_name(out, GIT_REFNAME_MAX, name, flags); return git_reference_normalize_name(out, GIT_REFNAME_MAX, name, flags);
} }
...@@ -213,7 +219,7 @@ int git_reference_lookup_resolved( ...@@ -213,7 +219,7 @@ int git_reference_lookup_resolved(
scan_type = GIT_REF_SYMBOLIC; scan_type = GIT_REF_SYMBOLIC;
if ((error = reference_normalize_for_repo(scan_name, repo, name)) < 0) if ((error = reference_normalize_for_repo(scan_name, repo, name, true)) < 0)
return error; return error;
if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0)
...@@ -383,7 +389,7 @@ static int reference__create( ...@@ -383,7 +389,7 @@ static int reference__create(
if (ref_out) if (ref_out)
*ref_out = NULL; *ref_out = NULL;
error = reference_normalize_for_repo(normalized, repo, name); error = reference_normalize_for_repo(normalized, repo, name, true);
if (error < 0) if (error < 0)
return error; return error;
...@@ -404,7 +410,10 @@ static int reference__create( ...@@ -404,7 +410,10 @@ static int reference__create(
} else { } else {
git_refname_t normalized_target; git_refname_t normalized_target;
if ((error = reference_normalize_for_repo(normalized_target, repo, symbolic)) < 0) error = reference_normalize_for_repo(normalized_target, repo,
symbolic, git_reference__enable_symbolic_ref_target_validation);
if (error < 0)
return error; return error;
ref = git_reference__alloc_symbolic(normalized, normalized_target); ref = git_reference__alloc_symbolic(normalized, normalized_target);
...@@ -583,7 +592,7 @@ static int reference__rename(git_reference **out, git_reference *ref, const char ...@@ -583,7 +592,7 @@ static int reference__rename(git_reference **out, git_reference *ref, const char
assert(ref && new_name && signature); assert(ref && new_name && signature);
if ((error = reference_normalize_for_repo( if ((error = reference_normalize_for_repo(
normalized, git_reference_owner(ref), new_name)) < 0) normalized, git_reference_owner(ref), new_name, true)) < 0)
return error; return error;
...@@ -876,6 +885,7 @@ int git_reference__normalize_name( ...@@ -876,6 +885,7 @@ int git_reference__normalize_name(
int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC; int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC;
unsigned int process_flags; unsigned int process_flags;
bool normalize = (buf != NULL); bool normalize = (buf != NULL);
bool validate = (flags & GIT_REF_FORMAT__VALIDATION_DISABLE) == 0;
#ifdef GIT_USE_ICONV #ifdef GIT_USE_ICONV
git_path_iconv_t ic = GIT_PATH_ICONV_INIT; git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
...@@ -886,7 +896,7 @@ int git_reference__normalize_name( ...@@ -886,7 +896,7 @@ int git_reference__normalize_name(
process_flags = flags; process_flags = flags;
current = (char *)name; current = (char *)name;
if (*current == '/') if (validate && *current == '/')
goto cleanup; goto cleanup;
if (normalize) if (normalize)
...@@ -902,6 +912,13 @@ int git_reference__normalize_name( ...@@ -902,6 +912,13 @@ int git_reference__normalize_name(
} }
#endif #endif
if (!validate) {
git_buf_sets(buf, current);
error = git_buf_oom(buf) ? -1 : 0;
goto cleanup;
}
while (true) { while (true) {
segment_len = ensure_segment_validity(current); segment_len = ensure_segment_validity(current);
if (segment_len < 0) { if (segment_len < 0) {
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include "buffer.h" #include "buffer.h"
#include "oid.h" #include "oid.h"
extern bool git_reference__enable_symbolic_ref_target_validation;
#define GIT_REFS_DIR "refs/" #define GIT_REFS_DIR "refs/"
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/" #define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/" #define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/"
...@@ -53,6 +55,7 @@ ...@@ -53,6 +55,7 @@
#define GIT_REFS_STASH_FILE GIT_REFS_DIR GIT_STASH_FILE #define GIT_REFS_STASH_FILE GIT_REFS_DIR GIT_STASH_FILE
#define GIT_REF_FORMAT__PRECOMPOSE_UNICODE (1u << 16) #define GIT_REF_FORMAT__PRECOMPOSE_UNICODE (1u << 16)
#define GIT_REF_FORMAT__VALIDATION_DISABLE (1u << 15)
#define GIT_REFNAME_MAX 1024 #define GIT_REFNAME_MAX 1024
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "cache.h" #include "cache.h"
#include "global.h" #include "global.h"
#include "object.h" #include "object.h"
#include "refs.h"
void git_libgit2_version(int *major, int *minor, int *rev) void git_libgit2_version(int *major, int *minor, int *rev)
{ {
...@@ -193,6 +194,10 @@ int git_libgit2_opts(int key, ...) ...@@ -193,6 +194,10 @@ int git_libgit2_opts(int key, ...)
git_object__strict_input_validation = (va_arg(ap, int) != 0); git_object__strict_input_validation = (va_arg(ap, int) != 0);
break; break;
case GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION:
git_reference__enable_symbolic_ref_target_validation = (va_arg(ap, int) != 0);
break;
case GIT_OPT_SET_SSL_CIPHERS: case GIT_OPT_SET_SSL_CIPHERS:
#ifdef GIT_OPENSSL #ifdef GIT_OPENSSL
{ {
......
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