diff options
author | Jeff King <peff@peff.net> | 2017-03-20 21:28:49 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-03-21 11:18:41 -0700 |
commit | e4da43b1f063d227b5f7d2922d27458748763a2d (patch) | |
tree | 3631b191d2bbd3f7cbc6e98188d65b0fe7c1974a /builtin | |
parent | prefix_filename: drop length parameter (diff) | |
download | tgif-e4da43b1f063d227b5f7d2922d27458748763a2d.tar.xz |
prefix_filename: return newly allocated string
The prefix_filename() function returns a pointer to static
storage, which makes it easy to use dangerously. We already
fixed one buggy caller in hash-object recently, and the
calls in apply.c are suspicious (I didn't dig in enough to
confirm that there is a bug, but we call the function once
in apply_all_patches() and then again indirectly from
parse_chunk()).
Let's make it harder to get wrong by allocating the return
value. For simplicity, we'll do this even when the prefix is
empty (and we could just return the original file pointer).
That will cause us to allocate sometimes when we wouldn't
otherwise need to, but this function isn't called in
performance critical code-paths (and it already _might_
allocate on any given call, so a caller that cares about
performance is questionable anyway).
The downside is that the callers need to remember to free()
the result to avoid leaking. Most of them already used
xstrdup() on the result, so we know they are OK. The
remainder have been converted to use free() as appropriate.
I considered retaining a prefix_filename_unsafe() for cases
where we know the static lifetime is OK (and handling the
cleanup is awkward). This is only a handful of cases,
though, and it's not worth the mental energy in worrying
about whether the "unsafe" variant is OK to use in any
situation.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/config.c | 3 | ||||
-rw-r--r-- | builtin/hash-object.c | 2 | ||||
-rw-r--r-- | builtin/log.c | 2 | ||||
-rw-r--r-- | builtin/mailinfo.c | 11 | ||||
-rw-r--r-- | builtin/merge-file.c | 14 | ||||
-rw-r--r-- | builtin/rev-parse.c | 4 | ||||
-rw-r--r-- | builtin/worktree.c | 3 |
7 files changed, 21 insertions, 18 deletions
diff --git a/builtin/config.c b/builtin/config.c index 74f6c34d11..4f49a0edb9 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -527,8 +527,7 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (given_config_source.file) { if (!is_absolute_path(given_config_source.file) && prefix) given_config_source.file = - xstrdup(prefix_filename(prefix, - given_config_source.file)); + prefix_filename(prefix, given_config_source.file); } if (respect_includes == -1) diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 2ea36909d2..bbeaf20bcc 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -145,7 +145,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix) char *to_free = NULL; if (prefix) - arg = to_free = xstrdup(prefix_filename(prefix, arg)); + arg = to_free = prefix_filename(prefix, arg); hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg, flags, literally); free(to_free); diff --git a/builtin/log.c b/builtin/log.c index bfdc7a23d3..670229cbb4 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -1084,7 +1084,7 @@ static const char *set_outdir(const char *prefix, const char *output_directory) if (!output_directory) return prefix; - return xstrdup(prefix_filename(prefix, output_directory)); + return prefix_filename(prefix, output_directory); } static const char * const builtin_format_patch_usage[] = { diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index 681f07f54d..cfb667a594 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -11,13 +11,6 @@ static const char mailinfo_usage[] = "git mailinfo [-k | -b] [-m | --message-id] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] <msg> <patch> < mail >info"; -static char *prefix_copy(const char *prefix, const char *filename) -{ - if (!prefix || is_absolute_path(filename)) - return xstrdup(filename); - return xstrdup(prefix_filename(prefix, filename)); -} - int cmd_mailinfo(int argc, const char **argv, const char *prefix) { const char *def_charset; @@ -60,8 +53,8 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix) mi.input = stdin; mi.output = stdout; - msgfile = prefix_copy(prefix, argv[1]); - patchfile = prefix_copy(prefix, argv[2]); + msgfile = prefix_filename(prefix, argv[1]); + patchfile = prefix_filename(prefix, argv[2]); status = !!mailinfo(&mi, msgfile, patchfile); clear_mailinfo(&mi); diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 63cd943587..47dde7c39c 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -65,11 +65,18 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) } for (i = 0; i < 3; i++) { - const char *fname = prefix_filename(prefix, argv[i]); + char *fname; + int ret; + if (!names[i]) names[i] = argv[i]; - if (read_mmfile(mmfs + i, fname)) + + fname = prefix_filename(prefix, argv[i]); + ret = read_mmfile(mmfs + i, fname); + free(fname); + if (ret) return -1; + if (mmfs[i].size > MAX_XDIFF_SIZE || buffer_is_binary(mmfs[i].ptr, mmfs[i].size)) return error("Cannot merge binary files: %s", @@ -86,7 +93,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) if (ret >= 0) { const char *filename = argv[0]; - const char *fpath = prefix_filename(prefix, argv[0]); + char *fpath = prefix_filename(prefix, argv[0]); FILE *f = to_stdout ? stdout : fopen(fpath, "wb"); if (!f) @@ -98,6 +105,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) else if (fclose(f)) ret = error_errno("Could not close %s", filename); free(result.ptr); + free(fpath); } if (ret > 127) diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index c8035331e2..7cd01c2819 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -228,7 +228,9 @@ static int show_file(const char *arg, int output_prefix) if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) { if (output_prefix) { const char *prefix = startup_info->prefix; - show(prefix_filename(prefix, arg)); + char *fname = prefix_filename(prefix, arg); + show(fname); + free(fname); } else show(arg); return 1; diff --git a/builtin/worktree.c b/builtin/worktree.c index e38325e44b..9993ded41a 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -318,7 +318,8 @@ static int add(int ac, const char **av, const char *prefix) { struct add_opts opts; const char *new_branch_force = NULL; - const char *path, *branch; + char *path; + const char *branch; struct option options[] = { OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")), OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), |