futils: use our random function for mktemp `mktemp` on mingw is exceedingly deficient, using a single monotonically increasing alphabetic character and the pid. We need to use our own random number generator for temporary filenames.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
diff --git a/src/futils.c b/src/futils.c
index 318e878..42c3595 100644
--- a/src/futils.c
+++ b/src/futils.c
@@ -10,6 +10,8 @@
#include "runtime.h"
#include "strmap.h"
#include "hash.h"
+#include "rand.h"
+
#include <ctype.h>
#if GIT_WIN32
#include "win32/findfile.h"
@@ -27,23 +29,20 @@ int git_futils_mkpath2file(const char *file_path, const mode_t mode)
int git_futils_mktmp(git_str *path_out, const char *filename, mode_t mode)
{
const int open_flags = O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC;
- /* TMP_MAX is unrelated to mktemp but should provide a reasonable amount */
- unsigned int tries = TMP_MAX;
+ unsigned int tries = 32;
int fd;
while (tries--) {
+ uint64_t rand = git_rand_next();
+
git_str_sets(path_out, filename);
- git_str_puts(path_out, "_git2_XXXXXX");
+ git_str_puts(path_out, "_git2_");
+ git_str_encode_hexstr(path_out, (void *)&rand, sizeof(uint64_t));
if (git_str_oom(path_out))
return -1;
- /* Using mktemp is safe when we open with O_CREAT | O_EXCL */
- p_mktemp(path_out->ptr);
- /* mktemp sets template to empty string on failure */
- if (path_out->ptr[0] == '\0')
- break;
-
+ /* Note that we open with O_CREAT | O_EXCL */
if ((fd = p_open(path_out->ptr, open_flags, mode)) >= 0)
return fd;
}
diff --git a/src/futils.h b/src/futils.h
index 1827cba..a82ec41 100644
--- a/src/futils.h
+++ b/src/futils.h
@@ -177,11 +177,12 @@ extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags
* protected directory; the file created will created will honor
* the current `umask`. Writes the filename into path_out.
*
- * This function is *NOT* suitable for use in temporary directories
- * that are world writable. It uses `mktemp` (for portability) and
- * many `mktemp` implementations use weak random characters. It
- * should only be assumed to be suitable for atomically writing
- * a new file in a directory that you control.
+ * This function uses a high-quality PRNG seeded by the system's
+ * entropy pool _where available_ and falls back to a simple seed
+ * (time plus system information) when not. This is suitable for
+ * writing within a protected directory, but the system's safe
+ * temporary file creation functions should be preferred where
+ * available when writing into world-writable (temp) directories.
*
* @return On success, an open file descriptor, else an error code < 0.
*/