2424#include <git2/signature.h>
2525#include <git2/commit.h>
2626
27+ bool git_reference__enable_symbolic_ref_target_validation = true;
28+
2729GIT__USE_STRMAP
2830
2931#define DEFAULT_NESTING_LEVEL 5
@@ -178,7 +180,8 @@ int git_reference_name_to_id(
178180static int reference_normalize_for_repo (
179181 git_refname_t out ,
180182 git_repository * repo ,
181- const char * name )
183+ const char * name ,
184+ bool validate )
182185{
183186 int precompose ;
184187 unsigned int flags = GIT_REF_FORMAT_ALLOW_ONELEVEL ;
@@ -187,6 +190,9 @@ static int reference_normalize_for_repo(
187190 precompose )
188191 flags |= GIT_REF_FORMAT__PRECOMPOSE_UNICODE ;
189192
193+ if (!validate )
194+ flags |= GIT_REF_FORMAT__VALIDATION_DISABLE ;
195+
190196 return git_reference_normalize_name (out , GIT_REFNAME_MAX , name , flags );
191197}
192198
@@ -213,7 +219,7 @@ int git_reference_lookup_resolved(
213219
214220 scan_type = GIT_REF_SYMBOLIC ;
215221
216- if ((error = reference_normalize_for_repo (scan_name , repo , name )) < 0 )
222+ if ((error = reference_normalize_for_repo (scan_name , repo , name , true )) < 0 )
217223 return error ;
218224
219225 if ((error = git_repository_refdb__weakptr (& refdb , repo )) < 0 )
@@ -383,7 +389,7 @@ static int reference__create(
383389 if (ref_out )
384390 * ref_out = NULL ;
385391
386- error = reference_normalize_for_repo (normalized , repo , name );
392+ error = reference_normalize_for_repo (normalized , repo , name , true );
387393 if (error < 0 )
388394 return error ;
389395
@@ -404,7 +410,10 @@ static int reference__create(
404410 } else {
405411 git_refname_t normalized_target ;
406412
407- if ((error = reference_normalize_for_repo (normalized_target , repo , symbolic )) < 0 )
413+ error = reference_normalize_for_repo (normalized_target , repo ,
414+ symbolic , git_reference__enable_symbolic_ref_target_validation );
415+
416+ if (error < 0 )
408417 return error ;
409418
410419 ref = git_reference__alloc_symbolic (normalized , normalized_target );
@@ -583,7 +592,7 @@ static int reference__rename(git_reference **out, git_reference *ref, const char
583592 assert (ref && new_name && signature );
584593
585594 if ((error = reference_normalize_for_repo (
586- normalized , git_reference_owner (ref ), new_name )) < 0 )
595+ normalized , git_reference_owner (ref ), new_name , true )) < 0 )
587596 return error ;
588597
589598
@@ -876,6 +885,7 @@ int git_reference__normalize_name(
876885 int segment_len , segments_count = 0 , error = GIT_EINVALIDSPEC ;
877886 unsigned int process_flags ;
878887 bool normalize = (buf != NULL );
888+ bool validate = (flags & GIT_REF_FORMAT__VALIDATION_DISABLE ) == 0 ;
879889
880890#ifdef GIT_USE_ICONV
881891 git_path_iconv_t ic = GIT_PATH_ICONV_INIT ;
@@ -886,7 +896,7 @@ int git_reference__normalize_name(
886896 process_flags = flags ;
887897 current = (char * )name ;
888898
889- if (* current == '/' )
899+ if (validate && * current == '/' )
890900 goto cleanup ;
891901
892902 if (normalize )
@@ -902,6 +912,13 @@ int git_reference__normalize_name(
902912 }
903913#endif
904914
915+ if (!validate ) {
916+ git_buf_sets (buf , current );
917+
918+ error = git_buf_oom (buf ) ? -1 : 0 ;
919+ goto cleanup ;
920+ }
921+
905922 while (true) {
906923 segment_len = ensure_segment_validity (current );
907924 if (segment_len < 0 ) {
0 commit comments