Skip to content

Commit ef00d15

Browse files
iabervongitster
authored andcommitted
Tighten refspec processing
This changes the pattern matching code to not store the required final / before the *, and then to require each side to be a valid ref (or empty). In particular, any refspec that looks like it should be a pattern but doesn't quite meet the requirements will be found to be invalid as a fallback non-pattern. Signed-off-by: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 971f229 commit ef00d15

File tree

1 file changed

+38
-9
lines changed

1 file changed

+38
-9
lines changed

remote.c

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ static void read_config(void)
396396
struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
397397
{
398398
int i;
399+
int st;
399400
struct refspec *rs = xcalloc(sizeof(*rs), nr_refspec);
400401
for (i = 0; i < nr_refspec; i++) {
401402
const char *sp, *ep, *gp;
@@ -404,13 +405,15 @@ struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
404405
rs[i].force = 1;
405406
sp++;
406407
}
407-
gp = strchr(sp, '*');
408+
gp = strstr(sp, "/*");
408409
ep = strchr(sp, ':');
409410
if (gp && ep && gp > ep)
410411
gp = NULL;
411412
if (ep) {
412413
if (ep[1]) {
413-
const char *glob = strchr(ep + 1, '*');
414+
const char *glob = strstr(ep + 1, "/*");
415+
if (glob && glob[2])
416+
glob = NULL;
414417
if (!glob)
415418
gp = NULL;
416419
if (gp)
@@ -422,11 +425,24 @@ struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)
422425
} else {
423426
ep = sp + strlen(sp);
424427
}
428+
if (gp && gp + 2 != ep)
429+
gp = NULL;
425430
if (gp) {
426431
rs[i].pattern = 1;
427432
ep = gp;
428433
}
429434
rs[i].src = xstrndup(sp, ep - sp);
435+
436+
if (*rs[i].src) {
437+
st = check_ref_format(rs[i].src);
438+
if (st && st != CHECK_REF_FORMAT_ONELEVEL)
439+
die("Invalid refspec '%s'", refspec[i]);
440+
}
441+
if (rs[i].dst && *rs[i].dst) {
442+
st = check_ref_format(rs[i].dst);
443+
if (st && st != CHECK_REF_FORMAT_ONELEVEL)
444+
die("Invalid refspec '%s'", refspec[i]);
445+
}
430446
}
431447
return rs;
432448
}
@@ -543,7 +559,8 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec)
543559
if (!fetch->dst)
544560
continue;
545561
if (fetch->pattern) {
546-
if (!prefixcmp(needle, key)) {
562+
if (!prefixcmp(needle, key) &&
563+
needle[strlen(key)] == '/') {
547564
*result = xmalloc(strlen(value) +
548565
strlen(needle) -
549566
strlen(key) + 1);
@@ -790,7 +807,9 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
790807
{
791808
int i;
792809
for (i = 0; i < rs_nr; i++) {
793-
if (rs[i].pattern && !prefixcmp(src->name, rs[i].src))
810+
if (rs[i].pattern &&
811+
!prefixcmp(src->name, rs[i].src) &&
812+
src->name[strlen(rs[i].src)] == '/')
794813
return rs + i;
795814
}
796815
return NULL;
@@ -989,7 +1008,7 @@ int get_fetch_map(const struct ref *remote_refs,
9891008
struct ref ***tail,
9901009
int missing_ok)
9911010
{
992-
struct ref *ref_map, *rm;
1011+
struct ref *ref_map, **rmp;
9931012

9941013
if (refspec->pattern) {
9951014
ref_map = get_expanded_map(remote_refs, refspec);
@@ -1006,10 +1025,20 @@ int get_fetch_map(const struct ref *remote_refs,
10061025
}
10071026
}
10081027

1009-
for (rm = ref_map; rm; rm = rm->next) {
1010-
if (rm->peer_ref && check_ref_format(rm->peer_ref->name + 5))
1011-
die("* refusing to create funny ref '%s' locally",
1012-
rm->peer_ref->name);
1028+
for (rmp = &ref_map; *rmp; ) {
1029+
if ((*rmp)->peer_ref) {
1030+
int st = check_ref_format((*rmp)->peer_ref->name + 5);
1031+
if (st && st != CHECK_REF_FORMAT_ONELEVEL) {
1032+
struct ref *ignore = *rmp;
1033+
error("* Ignoring funny ref '%s' locally",
1034+
(*rmp)->peer_ref->name);
1035+
*rmp = (*rmp)->next;
1036+
free(ignore->peer_ref);
1037+
free(ignore);
1038+
continue;
1039+
}
1040+
}
1041+
rmp = &((*rmp)->next);
10131042
}
10141043

10151044
if (ref_map)

0 commit comments

Comments
 (0)