]> git.ipfire.org Git - thirdparty/git.git/commitdiff
apply: avoid fixed-size buffer in create_one_file()
authorRené Scharfe <l.s.r@web.de>
Fri, 5 Apr 2024 10:53:23 +0000 (12:53 +0200)
committerJunio C Hamano <gitster@pobox.com>
Fri, 5 Apr 2024 16:49:36 +0000 (09:49 -0700)
PATH_MAX is not always a hard limit and 'path' in create_one_file()
could be longer -- it's taken from the patch file and allocated
dynamically.  Allocate the name of the temporary file on the heap as
well instead of using a fixed-size buffer to avoid that arbitrary limit.

Resist the temptation of using the more convenient mkpath() to avoid
introducing a dependency on a static variable deep inside the apply
machinery.

Take care to work around (arguably buggy) implementations of free(3)
that modify errno, by calling it only after using the errno value.

Suggested-by: Jeff King <peff@peff.net>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
apply.c

diff --git a/apply.c b/apply.c
index 7608e3301ca0727dcfec0a579ed46390afa41ab0..925dbde71341a883009d4a212fe87662190d4a7d 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -4430,6 +4430,7 @@ static int create_one_file(struct apply_state *state,
                           const char *buf,
                           unsigned long size)
 {
+       char *newpath = NULL;
        int res;
 
        if (state->cached)
@@ -4491,24 +4492,26 @@ static int create_one_file(struct apply_state *state,
                unsigned int nr = getpid();
 
                for (;;) {
-                       char newpath[PATH_MAX];
-                       mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
+                       newpath = mkpathdup("%s~%u", path, nr);
                        res = try_create_file(state, newpath, mode, buf, size);
                        if (res < 0)
-                               return -1;
+                               goto out;
                        if (!res) {
                                if (!rename(newpath, path))
-                                       return 0;
+                                       goto out;
                                unlink_or_warn(newpath);
                                break;
                        }
                        if (errno != EEXIST)
                                break;
                        ++nr;
+                       FREE_AND_NULL(newpath);
                }
        }
-       return error_errno(_("unable to write file '%s' mode %o"),
-                          path, mode);
+       res = error_errno(_("unable to write file '%s' mode %o"), path, mode);
+out:
+       free(newpath);
+       return res;
 }
 
 static int add_conflicted_stages_file(struct apply_state *state,