avoid using mksnpath for refs

Like the previous commit, we'd like to avoid the assumption
that refs fit into PATH_MAX-sized buffers. These callsites
have an extra twist, though: they write the refnames using
mksnpath. This does two things beyond a regular snprintf:

  1. It quietly writes "/bad-path/" when truncation occurs.
     This saves the caller having to check the error code,
     but if you aren't actually feeding the result to a
     system call (and we aren't here), it's questionable.

  2. It calls cleanup_path(), which removes leading
     instances of "./".  That's questionable when dealing
     with refnames, as we could silently canonicalize a
     syntactically bogus refname into a valid one.

Let's convert each case to use a strbuf. This is preferable
to xstrfmt() because we can reuse the same buffer as we
loop.

Signed-off-by: Jeff King <peff@peff.net>
This commit is contained in:
Jeff King
2017-03-28 15:46:33 -04:00
committed by Junio C Hamano
parent 7f897b6f17
commit 6cd4a8982d

44
refs.c
View File

@ -429,29 +429,31 @@ int expand_ref(const char *str, int len, unsigned char *sha1, char **ref)
{ {
const char **p, *r; const char **p, *r;
int refs_found = 0; int refs_found = 0;
struct strbuf fullref = STRBUF_INIT;
*ref = NULL; *ref = NULL;
for (p = ref_rev_parse_rules; *p; p++) { for (p = ref_rev_parse_rules; *p; p++) {
char fullref[PATH_MAX];
unsigned char sha1_from_ref[20]; unsigned char sha1_from_ref[20];
unsigned char *this_result; unsigned char *this_result;
int flag; int flag;
this_result = refs_found ? sha1_from_ref : sha1; this_result = refs_found ? sha1_from_ref : sha1;
mksnpath(fullref, sizeof(fullref), *p, len, str); strbuf_reset(&fullref);
r = resolve_ref_unsafe(fullref, RESOLVE_REF_READING, strbuf_addf(&fullref, *p, len, str);
r = resolve_ref_unsafe(fullref.buf, RESOLVE_REF_READING,
this_result, &flag); this_result, &flag);
if (r) { if (r) {
if (!refs_found++) if (!refs_found++)
*ref = xstrdup(r); *ref = xstrdup(r);
if (!warn_ambiguous_refs) if (!warn_ambiguous_refs)
break; break;
} else if ((flag & REF_ISSYMREF) && strcmp(fullref, "HEAD")) { } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
warning("ignoring dangling symref %s.", fullref); warning("ignoring dangling symref %s.", fullref.buf);
} else if ((flag & REF_ISBROKEN) && strchr(fullref, '/')) { } else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) {
warning("ignoring broken ref %s.", fullref); warning("ignoring broken ref %s.", fullref.buf);
} }
} }
strbuf_release(&fullref);
return refs_found; return refs_found;
} }
@ -460,21 +462,22 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
char *last_branch = substitute_branch_name(&str, &len); char *last_branch = substitute_branch_name(&str, &len);
const char **p; const char **p;
int logs_found = 0; int logs_found = 0;
struct strbuf path = STRBUF_INIT;
*log = NULL; *log = NULL;
for (p = ref_rev_parse_rules; *p; p++) { for (p = ref_rev_parse_rules; *p; p++) {
unsigned char hash[20]; unsigned char hash[20];
char path[PATH_MAX];
const char *ref, *it; const char *ref, *it;
mksnpath(path, sizeof(path), *p, len, str); strbuf_reset(&path);
ref = resolve_ref_unsafe(path, RESOLVE_REF_READING, strbuf_addf(&path, *p, len, str);
ref = resolve_ref_unsafe(path.buf, RESOLVE_REF_READING,
hash, NULL); hash, NULL);
if (!ref) if (!ref)
continue; continue;
if (reflog_exists(path)) if (reflog_exists(path.buf))
it = path; it = path.buf;
else if (strcmp(ref, path) && reflog_exists(ref)) else if (strcmp(ref, path.buf) && reflog_exists(ref))
it = ref; it = ref;
else else
continue; continue;
@ -485,6 +488,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
if (!warn_ambiguous_refs) if (!warn_ambiguous_refs)
break; break;
} }
strbuf_release(&path);
free(last_branch); free(last_branch);
return logs_found; return logs_found;
} }
@ -944,6 +948,7 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
static char **scanf_fmts; static char **scanf_fmts;
static int nr_rules; static int nr_rules;
char *short_name; char *short_name;
struct strbuf resolved_buf = STRBUF_INIT;
if (!nr_rules) { if (!nr_rules) {
/* /*
@ -1002,7 +1007,6 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
*/ */
for (j = 0; j < rules_to_fail; j++) { for (j = 0; j < rules_to_fail; j++) {
const char *rule = ref_rev_parse_rules[j]; const char *rule = ref_rev_parse_rules[j];
char refname[PATH_MAX];
/* skip matched rule */ /* skip matched rule */
if (i == j) if (i == j)
@ -1013,9 +1017,10 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
* (with this previous rule) to a valid ref * (with this previous rule) to a valid ref
* read_ref() returns 0 on success * read_ref() returns 0 on success
*/ */
mksnpath(refname, sizeof(refname), strbuf_reset(&resolved_buf);
rule, short_name_len, short_name); strbuf_addf(&resolved_buf, rule,
if (ref_exists(refname)) short_name_len, short_name);
if (ref_exists(resolved_buf.buf))
break; break;
} }
@ -1023,10 +1028,13 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
* short name is non-ambiguous if all previous rules * short name is non-ambiguous if all previous rules
* haven't resolved to a valid ref * haven't resolved to a valid ref
*/ */
if (j == rules_to_fail) if (j == rules_to_fail) {
strbuf_release(&resolved_buf);
return short_name; return short_name;
}
} }
strbuf_release(&resolved_buf);
free(short_name); free(short_name);
return xstrdup(refname); return xstrdup(refname);
} }