[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: mkstemp always generates the same file if removed between invocation
From: |
Bruno Haible |
Subject: |
Re: mkstemp always generates the same file if removed between invocations |
Date: |
Fri, 13 Oct 2023 15:40:27 +0200 |
Hi,
Sterpu Mihai wrote:
> It seems the underlying implementation of mskstemp is different between
> glibc and gnulib.
> Specifically, in tempname.c function try_tempname_len.
> The local variable v of type random_value is initialized to 0 in gnulib:
>
> /* A random variable. */
> random_value v = 0;
>
> whereas in glibc the following little trick is done:
>
> random_value v = ((uintptr_t) &v) / alignof (max_align_t);
>
> This is then used as a parameter to function random_bits.
> I didn't debug this on Windows (I honestly don't even know how, I'm simply
> using a gcc release from winlibs ie.
> https://github.com/brechtsanders/winlibs_mingw - but I would be interested
> to find out how!) but what happens is
> that random_bits always returns the same, "stP1kAlM".
>
> The immediate consequence is that on Linux the following small application
> produces different temporary files at each invocation:
>
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <unistd.h>
>
> char tmpl[100];
>
> int main()
> {
> strncpy(tmpl, "stXXXXXX", 8);
> // create temp file
> int fd = mkstemp(tmpl);
> printf("%s\n", tmpl);
> //close and remove file immediately after
> close(fd);
> remove(tmpl);
> return 0;
> }
>
> while on Windows, when being compiled with mingw gcc it produces THE SAME
> OUTPUT for each invocation.
We need to be careful to not confuse the various implementations of mkstemp.
There are:
(1) mkstemp defined by mingw,
(2) mkstemp defined by gnulib on mingw,
(3) mkstemp defined by glibc on Linux,
(4) mkstemp defined by gnulib on Linux.
The one in (3) is a high-quality implementation.
(1) When I take your program and compile it on mingw, I get
$ $CC foo.c
$ ./a.exe
stP1kAlm
$ ./a.exe
stP1kAlm
So, that's a low-quality implementation.
Now, for (2) and (4), let's create a gnulib testdir:
./gnulib-tool --create-testdir --dir=../testdir4 --single-configure mkstemp
(4) When I compile this testdir on Linux with glibc, I see that
- config.status has
S["HAVE_MKSTEMP"]="1"
S["REPLACE_MKSTEMP"]="0"
- in the gllib/ directory, there is no mkstemp.o file.
This means that gnulib has decided that the glibc function is working right
and therefore does not need an override.
(2) When I
- compile this testdir for mingw,
- change foo.c for use with gnulib, i.e. add a '#include <config.h>' line
as first line,
- compile foo.c against gnulib:
$ $CC foo.c -Itestdir4/build-mingw64 -Itestdir4/build-mingw64/gllib \
testdir4/build-mingw64/gllib/libgnu.a
$ ./a.exe
stFfT70P
$ ./a.exe
stRqF8Lh
$ ./a.exe
stCo4Pvn
I get different file names each time. So, that's a high-quality
implementation.
Conclusions:
* The binaries that you ran are using the mingw mkstemp, not the gnulib
mkstemp.
* If they were using the gnulib mkstemp, you would not be seeing the problem
that you are seeing.
* Your source code analysis of tempname.c is incorrect. Despite
random_value v = 0;
randomness comes in through the first call
random_bits (&v, v)
which invokes getrandom, which relies on the Windows functions
BCryptGenRandom and CryptGenRandom.
Bruno