{"thread":{"id":"12734","subject":"[PATCH] Tighten refspec processing","startedAt":"2008-03-18T02:05:23Z","lastAt":"2008-03-18T02:05:23Z","messageCount":1,"participants":["Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"72335","messageId":"alpine.LNX.1.00.0803172204420.19665@iabervon.org","threadId":"12734","inReplyTo":null,"subject":"[PATCH] Tighten refspec processing","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-03-18T02:05:23Z","receivedAt":"2008-03-18T02:05:23Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"This changes the pattern matching code to not store the required final\n/ before the *, and then to require each side to be a valid ref (or\nempty). In particular, any refspec that looks like it should be a\npattern but doesn't quite meet the requirements will be found to be\ninvalid as a fallback non-pattern.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n---\n(replaces the earlier patch)\n\n remote.c |   47 ++++++++++++++++++++++++++++++++++++++---------\n 1 files changed, 38 insertions(+), 9 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex f3f7375..476b8ef 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -396,6 +396,7 @@ static void read_config(void)\n struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)\n {\n \tint i;\n+\tint st;\n \tstruct refspec *rs = xcalloc(sizeof(*rs), nr_refspec);\n \tfor (i = 0; i < nr_refspec; i++) {\n \t\tconst char *sp, *ep, *gp;\n@@ -404,13 +405,15 @@ struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)\n \t\t\trs[i].force = 1;\n \t\t\tsp++;\n \t\t}\n-\t\tgp = strchr(sp, '*');\n+\t\tgp = strstr(sp, \"/*\");\n \t\tep = strchr(sp, ':');\n \t\tif (gp && ep && gp > ep)\n \t\t\tgp = NULL;\n \t\tif (ep) {\n \t\t\tif (ep[1]) {\n-\t\t\t\tconst char *glob = strchr(ep + 1, '*');\n+\t\t\t\tconst char *glob = strstr(ep + 1, \"/*\");\n+\t\t\t\tif (glob && glob[2])\n+\t\t\t\t\tglob = NULL;\n \t\t\t\tif (!glob)\n \t\t\t\t\tgp = NULL;\n \t\t\t\tif (gp)\n@@ -422,11 +425,24 @@ struct refspec *parse_ref_spec(int nr_refspec, const char **refspec)\n \t\t} else {\n \t\t\tep = sp + strlen(sp);\n \t\t}\n+\t\tif (gp && gp + 2 != ep)\n+\t\t\tgp = NULL;\n \t\tif (gp) {\n \t\t\trs[i].pattern = 1;\n \t\t\tep = gp;\n \t\t}\n \t\trs[i].src = xstrndup(sp, ep - sp);\n+\n+\t\tif (*rs[i].src) {\n+\t\t\tst = check_ref_format(rs[i].src);\n+\t\t\tif (st && st != CHECK_REF_FORMAT_ONELEVEL)\n+\t\t\t\tdie(\"Invalid refspec '%s'\", refspec[i]);\n+\t\t}\n+\t\tif (rs[i].dst && *rs[i].dst) {\n+\t\t\tst = check_ref_format(rs[i].dst);\n+\t\t\tif (st && st != CHECK_REF_FORMAT_ONELEVEL)\n+\t\t\t\tdie(\"Invalid refspec '%s'\", refspec[i]);\n+\t\t}\n \t}\n \treturn rs;\n }\n@@ -543,7 +559,8 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec)\n \t\tif (!fetch->dst)\n \t\t\tcontinue;\n \t\tif (fetch->pattern) {\n-\t\t\tif (!prefixcmp(needle, key)) {\n+\t\t\tif (!prefixcmp(needle, key) &&\n+\t\t\t    needle[strlen(key)] == '/') {\n \t\t\t\t*result = xmalloc(strlen(value) +\n \t\t\t\t\t\t  strlen(needle) -\n \t\t\t\t\t\t  strlen(key) + 1);\n@@ -790,7 +807,9 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,\n {\n \tint i;\n \tfor (i = 0; i < rs_nr; i++) {\n-\t\tif (rs[i].pattern && !prefixcmp(src->name, rs[i].src))\n+\t\tif (rs[i].pattern && \n+\t\t    !prefixcmp(src->name, rs[i].src) &&\n+\t\t    src->name[strlen(rs[i].src)] == '/')\n \t\t\treturn rs + i;\n \t}\n \treturn NULL;\n@@ -989,7 +1008,7 @@ int get_fetch_map(const struct ref *remote_refs,\n \t\t  struct ref ***tail,\n \t\t  int missing_ok)\n {\n-\tstruct ref *ref_map, *rm;\n+\tstruct ref *ref_map, **rmp;\n \n \tif (refspec->pattern) {\n \t\tref_map = get_expanded_map(remote_refs, refspec);\n@@ -1006,10 +1025,20 @@ int get_fetch_map(const struct ref *remote_refs,\n \t\t}\n \t}\n \n-\tfor (rm = ref_map; rm; rm = rm->next) {\n-\t\tif (rm->peer_ref && check_ref_format(rm->peer_ref->name + 5))\n-\t\t\tdie(\"* refusing to create funny ref '%s' locally\",\n-\t\t\t    rm->peer_ref->name);\n+\tfor (rmp = &ref_map; *rmp; ) {\n+\t\tif ((*rmp)->peer_ref) {\n+\t\t\tint st = check_ref_format((*rmp)->peer_ref->name + 5);\n+\t\t\tif (st && st != CHECK_REF_FORMAT_ONELEVEL) {\n+\t\t\t\tstruct ref *ignore = *rmp;\n+\t\t\t\terror(\"* Ignoring funny ref '%s' locally\",\n+\t\t\t\t      (*rmp)->peer_ref->name);\n+\t\t\t\t*rmp = (*rmp)->next;\n+\t\t\t\tfree(ignore->peer_ref);\n+\t\t\t\tfree(ignore);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t}\n+\t\trmp = &((*rmp)->next);\n \t}\n \n \tif (ref_map)\n-- \n1.5.4.3.610.gea6cd\n"}]}