always check return value of close_tempfile
authorJeff King <peff@peff.net>
Tue, 5 Sep 2017 12:14:26 +0000 (08:14 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 6 Sep 2017 08:19:53 +0000 (17:19 +0900)
If close_tempfile() encounters an error, then it deletes the
tempfile and resets the "struct tempfile". But many code
paths ignore the return value and continue to use the
tempfile. Instead, we should generally treat this the same
as a write() error.

Note that in the postimage of some of these cases our error
message will be bogus after a failed close because we look
at tempfile->filename (either directly or via get_tempfile_path).
But after the failed close resets the tempfile object, this
is guaranteed to be the empty string. That will be addressed
in a future patch (because there are many more cases of the
same problem than just these instances).

Note also in the hunk in gpg-interface.c that it's fine to
call delete_tempfile() in the error path, even if
close_tempfile() failed and already deleted the file. The
tempfile code is smart enough to know the second deletion is
a noop.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff.c
gpg-interface.c
shallow.c
diff --git a/diff.c b/diff.c
index 3d3e553a98bc4fd83d2f79515056c4116086b5df..fdb974014b4266ae5d4c6e6735097321bc29ed24 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -3738,9 +3738,9 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
                blob = buf.buf;
                size = buf.len;
        }
-       if (write_in_full(fd, blob, size) != size)
+       if (write_in_full(fd, blob, size) != size ||
+           close_tempfile(&temp->tempfile))
                die_errno("unable to write temp-file");
-       close_tempfile(&temp->tempfile);
        temp->name = get_tempfile_path(&temp->tempfile);
        oid_to_hex_r(temp->hex, oid);
        xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode);
index 455b6c04b4dde644844126ab77db8b2d7b070a54..05ca6ecbfd915a31fe468053560300e1f4873cc3 100644 (file)
@@ -209,13 +209,13 @@ int verify_signed_buffer(const char *payload, size_t payload_size,
        fd = mks_tempfile_t(&temp, ".git_vtag_tmpXXXXXX");
        if (fd < 0)
                return error_errno(_("could not create temporary file"));
-       if (write_in_full(fd, signature, signature_size) < 0) {
+       if (write_in_full(fd, signature, signature_size) < 0 ||
+           close_tempfile(&temp) < 0) {
                error_errno(_("failed writing detached signature to '%s'"),
                            temp.filename.buf);
                delete_tempfile(&temp);
                return -1;
        }
-       close_tempfile(&temp);
 
        argv_array_pushl(&gpg.args,
                         gpg_program,
index c7fd68ace09866ab791b145de6b6317fa909376b..f49e6ae122b6af2a06a7b4bb80b60f9f285950a5 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -295,10 +295,10 @@ const char *setup_temporary_shallow(const struct oid_array *extra)
        if (write_shallow_commits(&sb, 0, extra)) {
                fd = xmks_tempfile(&temp, git_path("shallow_XXXXXX"));
 
-               if (write_in_full(fd, sb.buf, sb.len) != sb.len)
+               if (write_in_full(fd, sb.buf, sb.len) != sb.len ||
+                   close_tempfile(&temp) < 0)
                        die_errno("failed to write to %s",
                                  get_tempfile_path(&temp));
-               close_tempfile(&temp);
                strbuf_release(&sb);
                return get_tempfile_path(&temp);
        }