{"thread":{"id":"64573","subject":"[PATCH 0/4] ban mktemp(3)","startedAt":"2025-12-03T10:45:14Z","lastAt":"2025-12-08T20:33:09Z","messageCount":19,"participants":["René Scharfe","Jeff King","Chris Torek","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"531602","messageId":"784f495a-4b1a-4acf-96cd-599243ef9e27@web.de","threadId":"64573","inReplyTo":null,"subject":"[PATCH 0/4] ban mktemp(3)","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-03T10:45:13Z","receivedAt":"2025-12-03T10:45:14Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"mktemp(3) is insecure and POSIX.1-2008 no longer specifies it.  Stop\nusing it.\n\n  wrapper: add git_mkdtemp()\n  compat: use git_mkdtemp()\n  compat: remove mingw_mktemp()\n  banned.h: ban mktemp(3)\n\n banned.h             |  3 +++\n compat/mingw-posix.h |  3 ---\n compat/mingw.c       | 12 ------------\n compat/mkdtemp.c     |  4 +---\n wrapper.c            | 17 +++++++++++++++--\n wrapper.h            |  2 ++\n 6 files changed, 21 insertions(+), 20 deletions(-)\n\n-- \n2.52.0\n"},{"id":"531617","messageId":"65c997a7-e480-4617-a761-fc9dc8a7b20d@web.de","threadId":"64573","inReplyTo":"784f495a-4b1a-4acf-96cd-599243ef9e27@web.de","subject":"[PATCH 1/4] wrapper: add git_mkdtemp()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-03T10:51:48Z","receivedAt":"2025-12-03T10:51:50Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Extend git_mkstemps_mode() to optionally call mkdir(2) instead of\nopen(2), then use that ability to create a mkdtemp(3) replacement,\ngit_mkdtemp().  We'll start using it in the next commit.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n wrapper.c | 17 +++++++++++++++--\n wrapper.h |  2 ++\n 2 files changed, 17 insertions(+), 2 deletions(-)\n\ndiff --git a/wrapper.c b/wrapper.c\nindex d5976b3e7e..6ddf4eb66b 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -429,7 +429,7 @@ int xmkstemp(char *filename_template)\n #undef TMP_MAX\n #define TMP_MAX 16384\n \n-int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n+static int git_mkdstemps_mode(char *pattern, int suffix_len, int mode, bool dir)\n {\n \tstatic const char letters[] =\n \t\t\"abcdefghijklmnopqrstuvwxyz\"\n@@ -471,7 +471,10 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n \t\t\tv /= num_letters;\n \t\t}\n \n-\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n+\t\tif (dir)\n+\t\t\tfd = mkdir(pattern, mode);\n+\t\telse\n+\t\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n \t\tif (fd >= 0)\n \t\t\treturn fd;\n \t\t/*\n@@ -486,6 +489,16 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n \treturn -1;\n }\n \n+char *git_mkdtemp(char *pattern)\n+{\n+\treturn git_mkdstemps_mode(pattern, 0, 0700, true) ? NULL : pattern;\n+}\n+\n+int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n+{\n+\treturn git_mkdstemps_mode(pattern, suffix_len, mode, false);\n+}\n+\n int git_mkstemp_mode(char *pattern, int mode)\n {\n \t/* mkstemp is just mkstemps with no suffix */\ndiff --git a/wrapper.h b/wrapper.h\nindex 44a8597ac3..15ac3bab6e 100644\n--- a/wrapper.h\n+++ b/wrapper.h\n@@ -37,6 +37,8 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...);\n \n int xgethostname(char *buf, size_t len);\n \n+char *git_mkdtemp(char *pattern);\n+\n /* set default permissions by passing mode arguments to open(2) */\n int git_mkstemps_mode(char *pattern, int suffix_len, int mode);\n int git_mkstemp_mode(char *pattern, int mode);\n-- \n2.52.0\n"},{"id":"531618","messageId":"4c70b527-9c40-4396-8c8c-95177c5d92f0@web.de","threadId":"64573","inReplyTo":"784f495a-4b1a-4acf-96cd-599243ef9e27@web.de","subject":"[PATCH 2/4] compat: use git_mkdtemp()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-03T10:52:30Z","receivedAt":"2025-12-03T10:52:32Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"A file might appear at the path returned by mktemp(3) before we call\nmkdir(2).  Use the more robust git_mkdtemp() instead, which retries a\nnumber of times and doesn't need to call lstat(2).\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n compat/mkdtemp.c | 4 +---\n 1 file changed, 1 insertion(+), 3 deletions(-)\n\ndiff --git a/compat/mkdtemp.c b/compat/mkdtemp.c\nindex 1136119592..fcdd4e01e1 100644\n--- a/compat/mkdtemp.c\n+++ b/compat/mkdtemp.c\n@@ -2,7 +2,5 @@\n \n char *gitmkdtemp(char *template)\n {\n-\tif (!*mktemp(template) || mkdir(template, 0700))\n-\t\treturn NULL;\n-\treturn template;\n+\treturn git_mkdtemp(template);\n }\n-- \n2.52.0\n"},{"id":"531619","messageId":"fdf6e8f3-d547-4331-95c7-75b44ae6c01f@web.de","threadId":"64573","inReplyTo":"784f495a-4b1a-4acf-96cd-599243ef9e27@web.de","subject":"[PATCH 3/4] compat: remove mingw_mktemp()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-03T10:52:53Z","receivedAt":"2025-12-03T10:53:01Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Remove the mktemp(3) compatibility function now that its last caller was\nremoved by the previous commit.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n compat/mingw-posix.h |  3 ---\n compat/mingw.c       | 12 ------------\n 2 files changed, 15 deletions(-)\n\ndiff --git a/compat/mingw-posix.h b/compat/mingw-posix.h\nindex 631a208684..0939feff27 100644\n--- a/compat/mingw-posix.h\n+++ b/compat/mingw-posix.h\n@@ -241,9 +241,6 @@ int mingw_chdir(const char *dirname);\n int mingw_chmod(const char *filename, int mode);\n #define chmod mingw_chmod\n \n-char *mingw_mktemp(char *template);\n-#define mktemp mingw_mktemp\n-\n char *mingw_getcwd(char *pointer, int len);\n #define getcwd mingw_getcwd\n \ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 90ba5cea9d..939f938fe2 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1164,18 +1164,6 @@ unsigned int sleep (unsigned int seconds)\n \treturn 0;\n }\n \n-char *mingw_mktemp(char *template)\n-{\n-\twchar_t wtemplate[MAX_PATH];\n-\tif (xutftowcs_path(wtemplate, template) < 0)\n-\t\treturn NULL;\n-\tif (!_wmktemp(wtemplate))\n-\t\treturn NULL;\n-\tif (xwcstoutf(template, wtemplate, strlen(template) + 1) < 0)\n-\t\treturn NULL;\n-\treturn template;\n-}\n-\n int mkstemp(char *template)\n {\n \treturn git_mkstemp_mode(template, 0600);\n-- \n2.52.0\n"},{"id":"531620","messageId":"37a36748-f357-403e-9a98-21d0f8a8fb41@web.de","threadId":"64573","inReplyTo":"784f495a-4b1a-4acf-96cd-599243ef9e27@web.de","subject":"[PATCH 4/4] banned.h: ban mktemp(3)","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-03T10:53:06Z","receivedAt":"2025-12-03T10:53:08Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Older versions of mktemp(3) generate easily guessable file names.  The\nfunction checks if the generated name is used, which is unreliable, as\na file with that name might then be created by some other process before\nwe can do it ourselves.  The function was dropped from POSIX due to its\nsecurity problems.  Forbid its use.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n banned.h | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/banned.h b/banned.h\nindex 44e76bd90a..2b934c8c43 100644\n--- a/banned.h\n+++ b/banned.h\n@@ -41,4 +41,7 @@\n #undef asctime_r\n #define asctime_r(t, buf) BANNED(asctime_r)\n \n+#undef mktemp\n+#define mktemp(x) BANNED(mktemp)\n+\n #endif /* BANNED_H */\n-- \n2.52.0\n"},{"id":"531627","messageId":"20251203161154.GA44940@coredump.intra.peff.net","threadId":"64573","inReplyTo":"4c70b527-9c40-4396-8c8c-95177c5d92f0@web.de","subject":"Re: [PATCH 2/4] compat: use git_mkdtemp()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-12-03T16:11:54Z","receivedAt":"2025-12-03T16:12:05Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Dec 03, 2025 at 11:52:30AM +0100, René Scharfe wrote:\n\n> A file might appear at the path returned by mktemp(3) before we call\n> mkdir(2).  Use the more robust git_mkdtemp() instead, which retries a\n> number of times and doesn't need to call lstat(2).\n\nThis seems like a good idea. At least one of the mkdtemp() callers was\nusing $TMPDIR, so this was a potential security-sensitive race.\n\n> diff --git a/compat/mkdtemp.c b/compat/mkdtemp.c\n> index 1136119592..fcdd4e01e1 100644\n> --- a/compat/mkdtemp.c\n> +++ b/compat/mkdtemp.c\n> @@ -2,7 +2,5 @@\n>  \n>  char *gitmkdtemp(char *template)\n>  {\n> -\tif (!*mktemp(template) || mkdir(template, 0700))\n> -\t\treturn NULL;\n> -\treturn template;\n> +\treturn git_mkdtemp(template);\n>  }\n\nOK, so now we have gitmkdtemp() and git_mkdtemp(), which are also now\nthe exact same thing. That seems overly complicated. ;)\n\nThis one is a conditionally-compiled wrapper for NO_MKDTEMP. But since\nwe always have git_mkdtemp() available (as of your first patch), can't\nwe just point at it directly with the macro?\n\nLike this:\n\ndiff --git a/Makefile b/Makefile\nindex 237b56fc9d..8226aed443 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1919,7 +1919,6 @@ ifdef NO_SETENV\n endif\n ifdef NO_MKDTEMP\n \tCOMPAT_CFLAGS += -DNO_MKDTEMP\n-\tCOMPAT_OBJS += compat/mkdtemp.o\n endif\n ifdef MKDIR_WO_TRAILING_SLASH\n \tCOMPAT_CFLAGS += -DMKDIR_WO_TRAILING_SLASH\ndiff --git a/compat/mkdtemp.c b/compat/mkdtemp.c\ndeleted file mode 100644\nindex fcdd4e01e1..0000000000\n--- a/compat/mkdtemp.c\n+++ /dev/null\n@@ -1,6 +0,0 @@\n-#include \"../git-compat-util.h\"\n-\n-char *gitmkdtemp(char *template)\n-{\n-\treturn git_mkdtemp(template);\n-}\ndiff --git a/compat/posix.h b/compat/posix.h\nindex 067a00f33b..245386fa4a 100644\n--- a/compat/posix.h\n+++ b/compat/posix.h\n@@ -329,8 +329,7 @@ int gitsetenv(const char *, const char *, int);\n #endif\n \n #ifdef NO_MKDTEMP\n-#define mkdtemp gitmkdtemp\n-char *gitmkdtemp(char *);\n+#define mkdtemp git_mkdtemp\n #endif\n \n #ifdef NO_UNSETENV\ndiff --git a/meson.build b/meson.build\nindex f1b3615659..090b1911ca 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -1401,7 +1401,6 @@ checkfuncs = {\n   'strlcpy' : ['strlcpy.c'],\n   'strtoull' : [],\n   'setenv' : ['setenv.c'],\n-  'mkdtemp' : ['mkdtemp.c'],\n   'initgroups' : [],\n   'strtoumax' : ['strtoumax.c', 'strtoimax.c'],\n   'pread' : ['pread.c'],\n\n\nWe could even take it a step further and just always use git_mkdtemp(),\nlike we were discussing elsewhere for mkstemp(). And then the makefile\nknobs can go away, too, like:\n\ndiff --git a/Makefile b/Makefile\nindex 8226aed443..8ef5497c10 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -68,8 +68,6 @@ include shared.mak\n #\n # Define NO_UNSETENV if you don't have unsetenv in the C library.\n #\n-# Define NO_MKDTEMP if you don't have mkdtemp in the C library.\n-#\n # Define MKDIR_WO_TRAILING_SLASH if your mkdir() can't deal with trailing slash.\n #\n # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd\ndiff --git a/compat/posix.h b/compat/posix.h\nindex 245386fa4a..c49d67e653 100644\n--- a/compat/posix.h\n+++ b/compat/posix.h\n@@ -328,9 +328,7 @@ ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);\n int gitsetenv(const char *, const char *, int);\n #endif\n \n-#ifdef NO_MKDTEMP\n #define mkdtemp git_mkdtemp\n-#endif\n \n #ifdef NO_UNSETENV\n #define unsetenv gitunsetenv\ndiff --git a/configure.ac b/configure.ac\nindex cfb50112bf..8e61186f18 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -1140,12 +1140,6 @@ GIT_CHECK_FUNC(unsetenv,\n [NO_UNSETENV=YesPlease])\n GIT_CONF_SUBST([NO_UNSETENV])\n #\n-# Define NO_MKDTEMP if you don't have mkdtemp in the C library.\n-GIT_CHECK_FUNC(mkdtemp,\n-[NO_MKDTEMP=],\n-[NO_MKDTEMP=YesPlease])\n-GIT_CONF_SUBST([NO_MKDTEMP])\n-#\n # Define NO_INITGROUPS if you don't have initgroups in the C library.\n GIT_CHECK_FUNC(initgroups,\n [NO_INITGROUPS=],\ndiff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt\nindex 479163ab5c..d28de227f5 100644\n--- a/contrib/buildsystems/CMakeLists.txt\n+++ b/contrib/buildsystems/CMakeLists.txt\n@@ -374,7 +374,7 @@ endif()\n #function checks\n set(function_checks\n \tstrcasestr memmem strlcpy strtoimax strtoumax strtoull\n-\tsetenv mkdtemp poll pread memmem)\n+\tsetenv poll pread memmem)\n \n #unsetenv,hstrerror are incompatible with windows build\n if(NOT WIN32)\n@@ -411,10 +411,6 @@ if(NOT HAVE_SETENV)\n \tlist(APPEND compat_SOURCES compat/setenv.c)\n endif()\n \n-if(NOT HAVE_MKDTEMP)\n-\tlist(APPEND compat_SOURCES compat/mkdtemp.c)\n-endif()\n-\n if(NOT HAVE_PREAD)\n \tlist(APPEND compat_SOURCES compat/pread.c)\n endif()\n\n-Peff\n"},{"id":"531628","messageId":"20251203161233.GB44940@coredump.intra.peff.net","threadId":"64573","inReplyTo":"37a36748-f357-403e-9a98-21d0f8a8fb41@web.de","subject":"Re: [PATCH 4/4] banned.h: ban mktemp(3)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-12-03T16:12:33Z","receivedAt":"2025-12-03T16:12:35Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Dec 03, 2025 at 11:53:06AM +0100, René Scharfe wrote:\n\n> Older versions of mktemp(3) generate easily guessable file names.  The\n> function checks if the generated name is used, which is unreliable, as\n> a file with that name might then be created by some other process before\n> we can do it ourselves.  The function was dropped from POSIX due to its\n> security problems.  Forbid its use.\n\nGreat. I am happy to see this.\n\n-Peff\n"},{"id":"531656","messageId":"CAPx1GvfAFLZz_SA+mBe7o8Cu4sL0_U5zzerhpev=sp4asEwcPw@mail.gmail.com","threadId":"64573","inReplyTo":"65c997a7-e480-4617-a761-fc9dc8a7b20d@web.de","subject":"Re: [PATCH 1/4] wrapper: add git_mkdtemp()","fromName":"Chris Torek","fromEmail":"chris.torek@gmail.com","sentAt":"2025-12-04T11:51:57Z","receivedAt":"2025-12-04T11:52:11Z","isPatch":true,"sender":{"key":"chris.torek@gmail.com","avatar":"https://avatars.githubusercontent.com/u/16826774?v=4"},"body":"fairly trivial, but:\n\nOn Wed, Dec 3, 2025 at 2:52 AM René Scharfe <l.s.r@web.de> wrote:\n> Extend git_mkstemps_mode() to optionally call mkdir(2) instead of\n> open(2), then use that ability to create a mkdtemp(3) replacement,\n> git_mkdtemp().  We'll start using it in the next commit.\n[snip]\n> -               fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n> +               if (dir)\n> +                       fd = mkdir(pattern, mode);\n> +               else\n> +                       fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n\nmkdir() returns a success (0) / fail (-1) indication, rather than\na file descriptor, so this is kind of misleading.  I think a\ncomment mentioning it would suffice (but also be a good idea, lest\nsomeone later think it needs a close() call).\n\nChris\n"},{"id":"531692","messageId":"aebd0ffe-7914-4731-8f79-830bd3b5a147@web.de","threadId":"64573","inReplyTo":"20251203161154.GA44940@coredump.intra.peff.net","subject":"Re: [PATCH 2/4] compat: use git_mkdtemp()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-05T12:11:40Z","receivedAt":"2025-12-05T12:11:43Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"On 12/3/25 5:11 PM, Jeff King wrote:\n> On Wed, Dec 03, 2025 at 11:52:30AM +0100, René Scharfe wrote:\n> \n>> A file might appear at the path returned by mktemp(3) before we call\n>> mkdir(2).  Use the more robust git_mkdtemp() instead, which retries a\n>> number of times and doesn't need to call lstat(2).\n> \n> This seems like a good idea. At least one of the mkdtemp() callers was\n> using $TMPDIR, so this was a potential security-sensitive race.\n> \n>> diff --git a/compat/mkdtemp.c b/compat/mkdtemp.c\n>> index 1136119592..fcdd4e01e1 100644\n>> --- a/compat/mkdtemp.c\n>> +++ b/compat/mkdtemp.c\n>> @@ -2,7 +2,5 @@\n>>  \n>>  char *gitmkdtemp(char *template)\n>>  {\n>> -\tif (!*mktemp(template) || mkdir(template, 0700))\n>> -\t\treturn NULL;\n>> -\treturn template;\n>> +\treturn git_mkdtemp(template);\n>>  }\n> \n> OK, so now we have gitmkdtemp() and git_mkdtemp(), which are also now\n> the exact same thing. That seems overly complicated. ;)\n> \n> This one is a conditionally-compiled wrapper for NO_MKDTEMP. But since\n> we always have git_mkdtemp() available (as of your first patch), can't\n> we just point at it directly with the macro?\n\nA worthwhile cleanup if we stop at this point, but complicated by\ntargeting three build systems, the CMake build being broken on macOS and\nme only knowing how to fake NO_MKDEMP for make, leaving half the build\nspace untestable for me.\n\n> Like this:\n> \n> diff --git a/Makefile b/Makefile\n> index 237b56fc9d..8226aed443 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -1919,7 +1919,6 @@ ifdef NO_SETENV\n>  endif\n>  ifdef NO_MKDTEMP\n>  \tCOMPAT_CFLAGS += -DNO_MKDTEMP\n> -\tCOMPAT_OBJS += compat/mkdtemp.o\n>  endif\n>  ifdef MKDIR_WO_TRAILING_SLASH\n>  \tCOMPAT_CFLAGS += -DMKDIR_WO_TRAILING_SLASH\n> diff --git a/compat/mkdtemp.c b/compat/mkdtemp.c\n> deleted file mode 100644\n> index fcdd4e01e1..0000000000\n> --- a/compat/mkdtemp.c\n> +++ /dev/null\n> @@ -1,6 +0,0 @@\n> -#include \"../git-compat-util.h\"\n> -\n> -char *gitmkdtemp(char *template)\n> -{\n> -\treturn git_mkdtemp(template);\n> -}\n> diff --git a/compat/posix.h b/compat/posix.h\n> index 067a00f33b..245386fa4a 100644\n> --- a/compat/posix.h\n> +++ b/compat/posix.h\n> @@ -329,8 +329,7 @@ int gitsetenv(const char *, const char *, int);\n>  #endif\n>  \n>  #ifdef NO_MKDTEMP\n> -#define mkdtemp gitmkdtemp\n> -char *gitmkdtemp(char *);\n> +#define mkdtemp git_mkdtemp\n>  #endif\n>  \n>  #ifdef NO_UNSETENV\n> diff --git a/meson.build b/meson.build\n> index f1b3615659..090b1911ca 100644\n> --- a/meson.build\n> +++ b/meson.build\n> @@ -1401,7 +1401,6 @@ checkfuncs = {\n>    'strlcpy' : ['strlcpy.c'],\n>    'strtoull' : [],\n>    'setenv' : ['setenv.c'],\n> -  'mkdtemp' : ['mkdtemp.c'],\n>    'initgroups' : [],\n>    'strtoumax' : ['strtoumax.c', 'strtoimax.c'],\n>    'pread' : ['pread.c'],\n\nWe need to keep that dictionary entry to still define NO_MKDTEMP, and\njust empty the array of filenames.\n\ncontrib/buildsystems/CMakeLists.txt needs to be updated as well, like\nyou do below (keep in function_checks, remove from compat_SOURCES).\n\nAt the very least this cleanup should be done in a separated patch, as\nit's harder than it looks.\n\n> We could even take it a step further and just always use git_mkdtemp(),\n> like we were discussing elsewhere for mkstemp(). And then the makefile\n> knobs can go away, too, like:\n> \n> diff --git a/Makefile b/Makefile\n> index 8226aed443..8ef5497c10 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -68,8 +68,6 @@ include shared.mak\n>  #\n>  # Define NO_UNSETENV if you don't have unsetenv in the C library.\n>  #\n> -# Define NO_MKDTEMP if you don't have mkdtemp in the C library.\n> -#\n>  # Define MKDIR_WO_TRAILING_SLASH if your mkdir() can't deal with trailing slash.\n>  #\n>  # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd\n> diff --git a/compat/posix.h b/compat/posix.h\n> index 245386fa4a..c49d67e653 100644\n> --- a/compat/posix.h\n> +++ b/compat/posix.h\n> @@ -328,9 +328,7 @@ ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);\n>  int gitsetenv(const char *, const char *, int);\n>  #endif\n>  \n> -#ifdef NO_MKDTEMP\n>  #define mkdtemp git_mkdtemp\n> -#endif\n>  \n>  #ifdef NO_UNSETENV\n>  #define unsetenv gitunsetenv\n> diff --git a/configure.ac b/configure.ac\n> index cfb50112bf..8e61186f18 100644\n> --- a/configure.ac\n> +++ b/configure.ac\n> @@ -1140,12 +1140,6 @@ GIT_CHECK_FUNC(unsetenv,\n>  [NO_UNSETENV=YesPlease])\n>  GIT_CONF_SUBST([NO_UNSETENV])\n>  #\n> -# Define NO_MKDTEMP if you don't have mkdtemp in the C library.\n> -GIT_CHECK_FUNC(mkdtemp,\n> -[NO_MKDTEMP=],\n> -[NO_MKDTEMP=YesPlease])\n> -GIT_CONF_SUBST([NO_MKDTEMP])\n> -#\n>  # Define NO_INITGROUPS if you don't have initgroups in the C library.\n>  GIT_CHECK_FUNC(initgroups,\n>  [NO_INITGROUPS=],\n> diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt\n> index 479163ab5c..d28de227f5 100644\n> --- a/contrib/buildsystems/CMakeLists.txt\n> +++ b/contrib/buildsystems/CMakeLists.txt\n> @@ -374,7 +374,7 @@ endif()\n>  #function checks\n>  set(function_checks\n>  \tstrcasestr memmem strlcpy strtoimax strtoumax strtoull\n> -\tsetenv mkdtemp poll pread memmem)\n> +\tsetenv poll pread memmem)\n>  \n>  #unsetenv,hstrerror are incompatible with windows build\n>  if(NOT WIN32)\n> @@ -411,10 +411,6 @@ if(NOT HAVE_SETENV)\n>  \tlist(APPEND compat_SOURCES compat/setenv.c)\n>  endif()\n>  \n> -if(NOT HAVE_MKDTEMP)\n> -\tlist(APPEND compat_SOURCES compat/mkdtemp.c)\n> -endif()\n> -\n>  if(NOT HAVE_PREAD)\n>  \tlist(APPEND compat_SOURCES compat/pread.c)\n>  endif()\n\nRight.  Dropping this dependency and then deep cleaning the compat code\nis attractive and mostly sidesteps the build system complications.\nThat's for a later series.\n\nUltimately you'd prefer banning mkdtemp(3) instead of automatically\nredirecting to git_mkdtemp(), though, no?\n\nRené\n\n"},{"id":"531732","messageId":"xmqqikek7cn1.fsf@gitster.g","threadId":"64573","inReplyTo":"65c997a7-e480-4617-a761-fc9dc8a7b20d@web.de","subject":"Re: [PATCH 1/4] wrapper: add git_mkdtemp()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-12-05T23:05:38Z","receivedAt":"2025-12-05T23:05:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <l.s.r@web.de> writes:\n\n> -int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n> +static int git_mkdstemps_mode(char *pattern, int suffix_len, int mode, bool dir)\n\nThis is a file-scope static, so as long as it is understood by those\nwho futz with things in this file well, there is no need to go extra\nmile to avoid confusion, but the meaning of the returned value from\nthis function is vastly different depending on the value of \"dir\".\nIt used to be that you can subject it to write(2), but obviously\nthat is not relevant when you called mkdir(2) here.\n\n>  {\n>  \tstatic const char letters[] =\n>  \t\t\"abcdefghijklmnopqrstuvwxyz\"\n> @@ -471,7 +471,10 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n>  \t\t\tv /= num_letters;\n>  \t\t}\n>  \n> -\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n> +\t\tif (dir)\n> +\t\t\tfd = mkdir(pattern, mode);\n\nOK.  The caller calls this helper with 0700 (S_IRWXU), so that's\nprobably OK.  If we can make this into two helper functions with\ndistinct function signatures that share the majority of logic, it\nwould have been much nicer, but short of introducing a callback\nfunction I do not think of a good way, so I'll let it pass.\n\n> +\t\telse\n> +\t\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n>  \t\tif (fd >= 0)\n>  \t\t\treturn fd;\n"},{"id":"531733","messageId":"xmqqecp87cmz.fsf@gitster.g","threadId":"64573","inReplyTo":"20251203161154.GA44940@coredump.intra.peff.net","subject":"Re: [PATCH 2/4] compat: use git_mkdtemp()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-12-05T23:05:40Z","receivedAt":"2025-12-05T23:05:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> This one is a conditionally-compiled wrapper for NO_MKDTEMP. But since\n> we always have git_mkdtemp() available (as of your first patch), can't\n> we just point at it directly with the macro?\n\nYup, that is much nicer.\n"},{"id":"531739","messageId":"20251206021122.GC1714099@coredump.intra.peff.net","threadId":"64573","inReplyTo":"aebd0ffe-7914-4731-8f79-830bd3b5a147@web.de","subject":"Re: [PATCH 2/4] compat: use git_mkdtemp()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-12-06T02:11:22Z","receivedAt":"2025-12-06T02:11:23Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Dec 05, 2025 at 01:11:40PM +0100, René Scharfe wrote:\n\n> > This one is a conditionally-compiled wrapper for NO_MKDTEMP. But since\n> > we always have git_mkdtemp() available (as of your first patch), can't\n> > we just point at it directly with the macro?\n> \n> A worthwhile cleanup if we stop at this point, but complicated by\n> targeting three build systems, the CMake build being broken on macOS and\n> me only knowing how to fake NO_MKDEMP for make, leaving half the build\n> space untestable for me.\n> [...]\n> At the very least this cleanup should be done in a separated patch, as\n> it's harder than it looks.\n\nOK, I am convinced that it is not entirely trivial and can go in a\nseparate patch. :) Mostly I was surprised that you would not have\nfollowed through on an obvious cleanup opportunity.  It just turned out\nharder than I expected.\n\n> Right.  Dropping this dependency and then deep cleaning the compat code\n> is attractive and mostly sidesteps the build system complications.\n> That's for a later series.\n\nYup. Sounds reasonable.\n\n> Ultimately you'd prefer banning mkdtemp(3) instead of automatically\n> redirecting to git_mkdtemp(), though, no?\n\nI'm OK either way. Whatever we end up doing for mkstemp(), I think we\nshould match here.\n\nI do like being explicit that we are using our own wrapper and not the\nsystem function. But I wonder if it might make complications in\nthird-party code like clar, which calls mkdtemp(). If we don't have a\ncompat macro we'll have to patch the sources that we import into\nt/unit-tests/clar.\n\nSo maybe that is an argument that we should leave the \"#define mkdtemp\"\nin place.\n\n-Peff\n"},{"id":"531753","messageId":"64e62623-b911-4ddd-a481-05191853c0a6@web.de","threadId":"64573","inReplyTo":"784f495a-4b1a-4acf-96cd-599243ef9e27@web.de","subject":"[PATCH v2 0/5] ban mktemp(3)","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-06T13:21:06Z","receivedAt":"2025-12-06T13:21:17Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"mktemp(3) is insecure and POSIX.1-2008 no longer specifies it.  Stop\nusing it.\n\nChanges since v1:\n- add comment regarding return values of git_mkdstemps_mode()\n- add patch to drop trivialized gitmkdtemp()\n\n  wrapper: add git_mkdtemp()\n  compat: use git_mkdtemp()\n  compat: remove mingw_mktemp()\n  banned.h: ban mktemp(3)\n  compat: remove gitmkdtemp()\n\n Makefile                            |  1 -\n banned.h                            |  3 +++\n compat/mingw-posix.h                |  3 ---\n compat/mingw.c                      | 12 ------------\n compat/mkdtemp.c                    |  8 --------\n compat/posix.h                      |  3 +--\n contrib/buildsystems/CMakeLists.txt |  4 ----\n meson.build                         |  2 +-\n wrapper.c                           | 21 +++++++++++++++++++--\n wrapper.h                           |  2 ++\n 10 files changed, 26 insertions(+), 33 deletions(-)\n delete mode 100644 compat/mkdtemp.c\n\nRange-diff against v1:\n1:  830e6375aa ! 1:  413131caf6 wrapper: add git_mkdtemp()\n    @@ wrapper.c: int xmkstemp(char *filename_template)\n      #define TMP_MAX 16384\n      \n     -int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n    ++/*\n    ++ * Returns -1 on error, 0 if it created a directory, or an open file\n    ++ * descriptor to the created regular file.\n    ++ */\n     +static int git_mkdstemps_mode(char *pattern, int suffix_len, int mode, bool dir)\n      {\n      \tstatic const char letters[] =\n2:  889903eaa2 = 2:  f8850b2a92 compat: use git_mkdtemp()\n3:  255b97254f = 3:  6986b4b6bf compat: remove mingw_mktemp()\n4:  8300d2e224 = 4:  f34252f411 banned.h: ban mktemp(3)\n-:  ---------- > 5:  d106855a23 compat: remove gitmkdtemp()\n-- \n2.52.0\n"},{"id":"531754","messageId":"8045d953-2cee-4ffd-b3d2-cbf732d5c839@web.de","threadId":"64573","inReplyTo":"64e62623-b911-4ddd-a481-05191853c0a6@web.de","subject":"[PATCH v2 1/5] wrapper: add git_mkdtemp()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-06T13:27:39Z","receivedAt":"2025-12-06T13:27:42Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Extend git_mkstemps_mode() to optionally call mkdir(2) instead of\nopen(2), then use that ability to create a mkdtemp(3) replacement,\ngit_mkdtemp().  We'll start using it in the next commit.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n wrapper.c | 21 +++++++++++++++++++--\n wrapper.h |  2 ++\n 2 files changed, 21 insertions(+), 2 deletions(-)\n\ndiff --git a/wrapper.c b/wrapper.c\nindex d5976b3e7e..b794fb20e7 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -429,7 +429,11 @@ int xmkstemp(char *filename_template)\n #undef TMP_MAX\n #define TMP_MAX 16384\n \n-int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n+/*\n+ * Returns -1 on error, 0 if it created a directory, or an open file\n+ * descriptor to the created regular file.\n+ */\n+static int git_mkdstemps_mode(char *pattern, int suffix_len, int mode, bool dir)\n {\n \tstatic const char letters[] =\n \t\t\"abcdefghijklmnopqrstuvwxyz\"\n@@ -471,7 +475,10 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n \t\t\tv /= num_letters;\n \t\t}\n \n-\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n+\t\tif (dir)\n+\t\t\tfd = mkdir(pattern, mode);\n+\t\telse\n+\t\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n \t\tif (fd >= 0)\n \t\t\treturn fd;\n \t\t/*\n@@ -486,6 +493,16 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n \treturn -1;\n }\n \n+char *git_mkdtemp(char *pattern)\n+{\n+\treturn git_mkdstemps_mode(pattern, 0, 0700, true) ? NULL : pattern;\n+}\n+\n+int git_mkstemps_mode(char *pattern, int suffix_len, int mode)\n+{\n+\treturn git_mkdstemps_mode(pattern, suffix_len, mode, false);\n+}\n+\n int git_mkstemp_mode(char *pattern, int mode)\n {\n \t/* mkstemp is just mkstemps with no suffix */\ndiff --git a/wrapper.h b/wrapper.h\nindex 44a8597ac3..15ac3bab6e 100644\n--- a/wrapper.h\n+++ b/wrapper.h\n@@ -37,6 +37,8 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...);\n \n int xgethostname(char *buf, size_t len);\n \n+char *git_mkdtemp(char *pattern);\n+\n /* set default permissions by passing mode arguments to open(2) */\n int git_mkstemps_mode(char *pattern, int suffix_len, int mode);\n int git_mkstemp_mode(char *pattern, int mode);\n-- \n2.52.0\n"},{"id":"531755","messageId":"c8b15174-314e-4f10-94b0-e46f96bc75a4@web.de","threadId":"64573","inReplyTo":"64e62623-b911-4ddd-a481-05191853c0a6@web.de","subject":"[PATCH v2 2/5] compat: use git_mkdtemp()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-06T13:27:47Z","receivedAt":"2025-12-06T13:27:49Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"A file might appear at the path returned by mktemp(3) before we call\nmkdir(2).  Use the more robust git_mkdtemp() instead, which retries a\nnumber of times and doesn't need to call lstat(2).\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n compat/mkdtemp.c | 4 +---\n 1 file changed, 1 insertion(+), 3 deletions(-)\n\ndiff --git a/compat/mkdtemp.c b/compat/mkdtemp.c\nindex 1136119592..fcdd4e01e1 100644\n--- a/compat/mkdtemp.c\n+++ b/compat/mkdtemp.c\n@@ -2,7 +2,5 @@\n \n char *gitmkdtemp(char *template)\n {\n-\tif (!*mktemp(template) || mkdir(template, 0700))\n-\t\treturn NULL;\n-\treturn template;\n+\treturn git_mkdtemp(template);\n }\n-- \n2.52.0\n"},{"id":"531756","messageId":"88a8a282-d436-4948-b2d0-ee9e1449f578@web.de","threadId":"64573","inReplyTo":"64e62623-b911-4ddd-a481-05191853c0a6@web.de","subject":"[PATCH v2 3/5] compat: remove mingw_mktemp()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-06T13:28:26Z","receivedAt":"2025-12-06T13:28:33Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Remove the mktemp(3) compatibility function now that its last caller was\nremoved by the previous commit.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n compat/mingw-posix.h |  3 ---\n compat/mingw.c       | 12 ------------\n 2 files changed, 15 deletions(-)\n\ndiff --git a/compat/mingw-posix.h b/compat/mingw-posix.h\nindex 631a208684..0939feff27 100644\n--- a/compat/mingw-posix.h\n+++ b/compat/mingw-posix.h\n@@ -241,9 +241,6 @@ int mingw_chdir(const char *dirname);\n int mingw_chmod(const char *filename, int mode);\n #define chmod mingw_chmod\n \n-char *mingw_mktemp(char *template);\n-#define mktemp mingw_mktemp\n-\n char *mingw_getcwd(char *pointer, int len);\n #define getcwd mingw_getcwd\n \ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 90ba5cea9d..939f938fe2 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1164,18 +1164,6 @@ unsigned int sleep (unsigned int seconds)\n \treturn 0;\n }\n \n-char *mingw_mktemp(char *template)\n-{\n-\twchar_t wtemplate[MAX_PATH];\n-\tif (xutftowcs_path(wtemplate, template) < 0)\n-\t\treturn NULL;\n-\tif (!_wmktemp(wtemplate))\n-\t\treturn NULL;\n-\tif (xwcstoutf(template, wtemplate, strlen(template) + 1) < 0)\n-\t\treturn NULL;\n-\treturn template;\n-}\n-\n int mkstemp(char *template)\n {\n \treturn git_mkstemp_mode(template, 0600);\n-- \n2.52.0\n"},{"id":"531757","messageId":"e014345e-9472-4692-8985-1a56b64eef61@web.de","threadId":"64573","inReplyTo":"64e62623-b911-4ddd-a481-05191853c0a6@web.de","subject":"[PATCH v2 4/5] banned.h: ban mktemp(3)","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-06T13:29:43Z","receivedAt":"2025-12-06T13:29:50Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Older versions of mktemp(3) generate easily guessable file names.  The\nfunction checks if the generated name is used, which is unreliable, as\na file with that name might then be created by some other process before\nwe can do it ourselves.  The function was dropped from POSIX due to its\nsecurity problems.  Forbid its use.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n banned.h | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/banned.h b/banned.h\nindex 44e76bd90a..2b934c8c43 100644\n--- a/banned.h\n+++ b/banned.h\n@@ -41,4 +41,7 @@\n #undef asctime_r\n #define asctime_r(t, buf) BANNED(asctime_r)\n \n+#undef mktemp\n+#define mktemp(x) BANNED(mktemp)\n+\n #endif /* BANNED_H */\n-- \n2.52.0\n"},{"id":"531758","messageId":"b0ed5848-ab28-4255-9933-b1d15ac9e13c@web.de","threadId":"64573","inReplyTo":"64e62623-b911-4ddd-a481-05191853c0a6@web.de","subject":"[PATCH v2 5/5] compat: remove gitmkdtemp()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-06T13:35:39Z","receivedAt":"2025-12-06T13:35:46Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"gitmkdtemp() has become a trivial wrapper around git_mkdtemp().  Remove\nthis now unnecessary layer of indirection.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\nOnly tested with make.\n\n Makefile                            | 1 -\n compat/mkdtemp.c                    | 6 ------\n compat/posix.h                      | 3 +--\n contrib/buildsystems/CMakeLists.txt | 4 ----\n meson.build                         | 2 +-\n 5 files changed, 2 insertions(+), 14 deletions(-)\n delete mode 100644 compat/mkdtemp.c\n\ndiff --git a/Makefile b/Makefile\nindex 237b56fc9d..8226aed443 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1919,7 +1919,6 @@ ifdef NO_SETENV\n endif\n ifdef NO_MKDTEMP\n \tCOMPAT_CFLAGS += -DNO_MKDTEMP\n-\tCOMPAT_OBJS += compat/mkdtemp.o\n endif\n ifdef MKDIR_WO_TRAILING_SLASH\n \tCOMPAT_CFLAGS += -DMKDIR_WO_TRAILING_SLASH\ndiff --git a/compat/mkdtemp.c b/compat/mkdtemp.c\ndeleted file mode 100644\nindex fcdd4e01e1..0000000000\n--- a/compat/mkdtemp.c\n+++ /dev/null\n@@ -1,6 +0,0 @@\n-#include \"../git-compat-util.h\"\n-\n-char *gitmkdtemp(char *template)\n-{\n-\treturn git_mkdtemp(template);\n-}\ndiff --git a/compat/posix.h b/compat/posix.h\nindex 067a00f33b..245386fa4a 100644\n--- a/compat/posix.h\n+++ b/compat/posix.h\n@@ -329,8 +329,7 @@ int gitsetenv(const char *, const char *, int);\n #endif\n \n #ifdef NO_MKDTEMP\n-#define mkdtemp gitmkdtemp\n-char *gitmkdtemp(char *);\n+#define mkdtemp git_mkdtemp\n #endif\n \n #ifdef NO_UNSETENV\ndiff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt\nindex 479163ab5c..28877feb9d 100644\n--- a/contrib/buildsystems/CMakeLists.txt\n+++ b/contrib/buildsystems/CMakeLists.txt\n@@ -411,10 +411,6 @@ if(NOT HAVE_SETENV)\n \tlist(APPEND compat_SOURCES compat/setenv.c)\n endif()\n \n-if(NOT HAVE_MKDTEMP)\n-\tlist(APPEND compat_SOURCES compat/mkdtemp.c)\n-endif()\n-\n if(NOT HAVE_PREAD)\n \tlist(APPEND compat_SOURCES compat/pread.c)\n endif()\ndiff --git a/meson.build b/meson.build\nindex f1b3615659..24c656681c 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -1401,7 +1401,7 @@ checkfuncs = {\n   'strlcpy' : ['strlcpy.c'],\n   'strtoull' : [],\n   'setenv' : ['setenv.c'],\n-  'mkdtemp' : ['mkdtemp.c'],\n+  'mkdtemp' : [],\n   'initgroups' : [],\n   'strtoumax' : ['strtoumax.c', 'strtoimax.c'],\n   'pread' : ['pread.c'],\n-- \n2.52.0\n"},{"id":"531860","messageId":"20251208203307.GD216526@coredump.intra.peff.net","threadId":"64573","inReplyTo":"64e62623-b911-4ddd-a481-05191853c0a6@web.de","subject":"Re: [PATCH v2 0/5] ban mktemp(3)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-12-08T20:33:07Z","receivedAt":"2025-12-08T20:33:09Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Dec 06, 2025 at 02:21:06PM +0100, René Scharfe wrote:\n\n> mktemp(3) is insecure and POSIX.1-2008 no longer specifies it.  Stop\n> using it.\n> \n> Changes since v1:\n> - add comment regarding return values of git_mkdstemps_mode()\n> - add patch to drop trivialized gitmkdtemp()\n\nThanks, this all looks reasonable to me. I don't have a system without\nmkdtemp() to test the meson change on, but I can confirm it builds on\nLinux for me using meson. ;)\n\n-Peff\n"}]}