apply: avoid fixed-size buffer in create_one_file()

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>

René Scharfe committed Apr 5, 2024 at 12:53 UTC 9126cb3186112f160a601e9a7eda29dd43227576
1 file changed +9 -6
apply.c
+9 -6
@@ -4430,6 +4430,7 @@ static int create_one_file(struct apply_state *state,
4430 const char *buf,
4431 unsigned long size)
4432 {
4433 + char *newpath = NULL;
4434 int res;
4435
4436 if (state->cached)
@@ -4491,24 +4492,26 @@ static int create_one_file(struct apply_state *state,
4492 unsigned int nr = getpid();
4493
4494 for (;;) {
4494 - char newpath[PATH_MAX];
4495 - mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
4495 + newpath = mkpathdup("%s~%u", path, nr);
4496 res = try_create_file(state, newpath, mode, buf, size);
4497 if (res < 0)
4498 - return -1;
4498 + goto out;
4499 if (!res) {
4500 if (!rename(newpath, path))
4501 - return 0;
4501 + goto out;
4502 unlink_or_warn(newpath);
4503 break;
4504 }
4505 if (errno != EEXIST)
4506 break;
4507 ++nr;
4508 + FREE_AND_NULL(newpath);
4509 }
4510 }
4510 - return error_errno(_("unable to write file '%s' mode %o"),
4511 - path, mode);
4511 + res = error_errno(_("unable to write file '%s' mode %o"), path, mode);
4512 +out:
4513 + free(newpath);
4514 + return res;
4515 }
4516
4517 static int add_conflicted_stages_file(struct apply_state *state,