bug-gnulib
[Top][All Lists]
Advanced

[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






reply via email to

[Prev in Thread] Current Thread [Next in Thread]