git/builtin
Jeff King 076aa2cbda tempfile: auto-allocate tempfiles on heap
The previous commit taught the tempfile code to give up
ownership over tempfiles that have been renamed or deleted.
That makes it possible to use a stack variable like this:

  struct tempfile t;

  create_tempfile(&t, ...);
  ...
  if (!err)
          rename_tempfile(&t, ...);
  else
          delete_tempfile(&t);

But doing it this way has a high potential for creating
memory errors. The tempfile we pass to create_tempfile()
ends up on a global linked list, and it's not safe for it to
go out of scope until we've called one of those two
deactivation functions.

Imagine that we add an early return from the function that
forgets to call delete_tempfile(). With a static or heap
tempfile variable, the worst case is that the tempfile hangs
around until the program exits (and some functions like
setup_shallow_temporary rely on this intentionally, creating
a tempfile and then leaving it for later cleanup).

But with a stack variable as above, this is a serious memory
error: the variable goes out of scope and may be filled with
garbage by the time the tempfile code looks at it.  Let's
see if we can make it harder to get this wrong.

Since many callers need to allocate arbitrary numbers of
tempfiles, we can't rely on static storage as a general
solution. So we need to turn to the heap. We could just ask
all callers to pass us a heap variable, but that puts the
burden on them to call free() at the right time.

Instead, let's have the tempfile code handle the heap
allocation _and_ the deallocation (when the tempfile is
deactivated and removed from the list).

This changes the return value of all of the creation
functions. For the cleanup functions (delete and rename),
we'll add one extra bit of safety: instead of taking a
tempfile pointer, we'll take a pointer-to-pointer and set it
to NULL after freeing the object. This makes it safe to
double-call functions like delete_tempfile(), as the second
call treats the NULL input as a noop. Several callsites
follow this pattern.

The resulting patch does have a fair bit of noise, as each
caller needs to be converted to handle:

  1. Storing a pointer instead of the struct itself.

  2. Passing the pointer instead of taking the struct
     address.

  3. Handling a "struct tempfile *" return instead of a file
     descriptor.

We could play games to make this less noisy. For example, by
defining the tempfile like this:

  struct tempfile {
	struct heap_allocated_part_of_tempfile {
                int fd;
                ...etc
        } *actual_data;
  }

Callers would continue to have a "struct tempfile", and it
would be "active" only when the inner pointer was non-NULL.
But that just makes things more awkward in the long run.
There aren't that many callers, so we can simply bite
the bullet and adjust all of them. And the compiler makes it
easy for us to find them all.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-09-06 17:19:54 +09:00
..
add.c Merge branch 'bw/submodule-config-cleanup' 2017-08-26 22:55:08 -07:00
am.c pack: move pack-closing functions 2017-08-23 15:12:06 -07:00
annotate.c
apply.c Convert read_mmblob to take struct object_id. 2016-09-07 12:59:42 -07:00
archive.c archive: read local configuration 2016-11-22 13:55:20 -08:00
bisect--helper.c
blame.c Merge branch 'po/read-graft-line' 2017-09-06 13:11:25 +09:00
branch.c builtin/branch: stop supporting the "--set-upstream" option 2017-08-17 13:33:20 -07:00
bundle.c bundle: use prefix_filename with bundle path 2017-03-21 11:18:41 -07:00
cat-file.c pack: move for_each_packed_object() 2017-08-23 15:12:07 -07:00
check-attr.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
check-ignore.c Merge branch 'bw/config-h' 2017-06-24 14:28:41 -07:00
check-mailmap.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
check-ref-format.c
checkout-index.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
checkout.c Merge branch 'bw/submodule-config-cleanup' 2017-08-26 22:55:08 -07:00
clean.c Merge branch 'jk/c99' 2017-08-11 13:26:58 -07:00
clone.c pack: move pack-closing functions 2017-08-23 15:12:06 -07:00
column.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
commit-tree.c sha1_name: convert get_sha1* to get_oid* 2017-07-17 13:54:51 -07:00
commit.c Merge branch 'bw/submodule-config-cleanup' 2017-08-26 22:55:08 -07:00
config.c Merge branch 'ab/free-and-null' 2017-06-24 14:28:41 -07:00
count-objects.c pack: move open_pack_index(), parse_pack_index() 2017-08-23 15:12:06 -07:00
credential.c credential: handle invalid arguments earlier 2017-05-30 14:45:03 +09:00
describe.c Merge branch 'sb/hashmap-cleanup' 2017-08-11 13:27:01 -07:00
diff-files.c submodule: remove gitmodules_config 2017-08-03 13:11:02 -07:00
diff-index.c submodule: remove gitmodules_config 2017-08-03 13:11:02 -07:00
diff-tree.c submodule: remove gitmodules_config 2017-08-03 13:11:02 -07:00
diff.c submodule: remove gitmodules_config 2017-08-03 13:11:02 -07:00
difftool.c sha1_file: convert index_fd to struct object_id 2017-08-20 21:52:08 -07:00
fast-export.c hashmap.h: compare function has access to a data field 2017-06-30 12:49:28 -07:00
fetch-pack.c Rename sha1_array to oid_array 2017-03-31 08:33:56 -07:00
fetch.c Merge branch 'jt/packmigrate' 2017-08-26 22:55:09 -07:00
fmt-merge-msg.c Merge branch 'dc/fmt-merge-msg-microcleanup' 2017-08-11 13:27:05 -07:00
for-each-ref.c for-each-ref: load config earlier 2017-07-13 12:42:51 -07:00
fsck.c Merge branch 'jt/packmigrate' 2017-08-26 22:55:09 -07:00
gc.c tempfile: auto-allocate tempfiles on heap 2017-09-06 17:19:54 +09:00
get-tar-commit-id.c
grep.c Merge branch 'bw/submodule-config-cleanup' 2017-08-26 22:55:08 -07:00
hash-object.c sha1_file: convert hash_sha1_file_literally to struct object_id 2017-08-20 21:52:53 -07:00
help.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
index-pack.c pack: move pack name-related functions 2017-08-23 15:12:06 -07:00
init-db.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
interpret-trailers.c Merge branch 'jk/trailers-parse' 2017-08-26 22:55:04 -07:00
log.c Merge branch 'jc/simplify-progress' 2017-08-24 10:20:02 -07:00
ls-files.c Merge branch 'bw/submodule-config-cleanup' 2017-08-26 22:55:08 -07:00
ls-remote.c wildmatch: remove unused wildopts parameter 2017-06-23 18:27:07 -07:00
ls-tree.c Merge branch 'bw/config-h' 2017-06-24 14:28:41 -07:00
mailinfo.c prefix_filename: return newly allocated string 2017-03-21 11:18:41 -07:00
mailsplit.c mailinfo & mailsplit: check for EOF while parsing 2017-05-08 12:18:19 +09:00
merge-base.c Merge branch 'bw/config-h' 2017-06-24 14:28:41 -07:00
merge-file.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
merge-index.c Convert GIT_SHA1_HEXSZ used for allocation to GIT_MAX_HEXSZ 2017-03-26 22:08:21 -07:00
merge-ours.c
merge-recursive.c i18n: merge-recursive: mark verbose message for translation 2016-09-15 13:17:32 -07:00
merge-tree.c tree-walk: convert fill_tree_descriptor() to object_id 2017-08-14 12:38:54 -07:00
merge.c Merge branch 'mg/killed-merge' 2017-08-26 22:55:10 -07:00
mktag.c
mktree.c mktree: plug memory leaks reported by Coverity 2017-05-08 12:18:19 +09:00
mv.c submodule: remove gitmodules_config 2017-08-03 13:11:02 -07:00
name-rev.c Merge branch 'ab/wildmatch' 2017-07-10 13:42:51 -07:00
notes.c Merge branch 'bw/object-id' 2017-08-11 13:26:56 -07:00
pack-objects.c pack: move open_pack_index(), parse_pack_index() 2017-08-23 15:12:06 -07:00
pack-redundant.c pack: move pack name-related functions 2017-08-23 15:12:06 -07:00
pack-refs.c refs: delete pack_refs() in favor of refs_pack_refs() 2017-04-14 03:53:25 -07:00
patch-id.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
prune-packed.c Merge branch 'jt/packmigrate' 2017-08-26 22:55:09 -07:00
prune.c progress: simplify "delayed" progress API 2017-08-19 14:01:34 -07:00
pull.c Merge branch 'ma/parse-maybe-bool' 2017-08-22 10:29:03 -07:00
push.c Merge branch 'ma/parse-maybe-bool' 2017-08-22 10:29:03 -07:00
read-tree.c submodule: remove gitmodules_config 2017-08-03 13:11:02 -07:00
rebase--helper.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
receive-pack.c pack: move pack-closing functions 2017-08-23 15:12:06 -07:00
reflog.c Merge branch 'ab/wildmatch' 2017-07-10 13:42:51 -07:00
remote-ext.c remote-{ext,fd}: print usage message on invalid arguments 2017-05-30 14:45:04 +09:00
remote-fd.c remote-{ext,fd}: print usage message on invalid arguments 2017-05-30 14:45:04 +09:00
remote.c Merge branch 'ma/parse-maybe-bool' 2017-08-22 10:29:03 -07:00
repack.c Merge branch 'bw/config-h' 2017-06-24 14:28:41 -07:00
replace.c sha1_file: convert index_fd to struct object_id 2017-08-20 21:52:08 -07:00
rerere.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
reset.c Merge branch 'bw/submodule-config-cleanup' 2017-08-26 22:55:08 -07:00
rev-list.c Merge branch 'jc/simplify-progress' 2017-08-24 10:20:02 -07:00
rev-parse.c sha1_name: convert GET_SHA1* flags to GET_OID* 2017-07-17 13:54:51 -07:00
revert.c cherry-pick/revert: reject --rerere-autoupdate when continuing 2017-08-02 15:16:09 -07:00
rm.c submodule: remove gitmodules_config 2017-08-03 13:11:02 -07:00
send-pack.c Merge branch 'ma/parse-maybe-bool' 2017-08-22 10:29:03 -07:00
shortlog.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
show-branch.c Merge branch 'jk/ref-filter-colors' 2017-08-11 13:26:58 -07:00
show-ref.c show-ref: remove a stale comment 2017-01-23 18:51:56 -08:00
stripspace.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
submodule--helper.c Merge branch 'bw/submodule-config-cleanup' 2017-08-26 22:55:08 -07:00
symbolic-ref.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
tag.c Merge branch 'ma/pager-per-subcommand-action' 2017-08-11 13:27:07 -07:00
unpack-file.c builtin/unpack-file: convert to struct object_id 2017-07-17 13:54:38 -07:00
unpack-objects.c Merge branch 'ab/free-and-null' 2017-06-24 14:28:41 -07:00
update-index.c sha1_file: convert index_path to struct object_id 2017-08-20 21:51:38 -07:00
update-ref.c builtin/update_ref: convert to struct object_id 2017-07-17 13:54:38 -07:00
update-server-info.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
upload-archive.c upload-archive: handle "-h" option early 2017-05-30 14:45:04 +09:00
var.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
verify-commit.c Merge branch 'bw/config-h' 2017-06-24 14:28:41 -07:00
verify-pack.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00
verify-tag.c Merge branch 'jk/ref-filter-colors' 2017-08-11 13:26:58 -07:00
worktree.c Merge branch 'ab/free-and-null' 2017-06-24 14:28:41 -07:00
write-tree.c config: don't include config.h by default 2017-06-15 12:56:22 -07:00