[libc-commits] [libc] [libc] Add tmpnam implementation (PR #204901)

Jeff Bailey via libc-commits libc-commits at lists.llvm.org
Sat Aug 1 00:24:31 PDT 2026


================
@@ -54,5 +54,92 @@ extern FILE *stderr;
 #ifndef SEEK_END
 #define SEEK_END 2
 #endif
+/*
+ * Derivation of L_tmpnam
+ * ------------------------------------------------------------
+ *
+ * Generated pathnames have the form: /tmp/XXXXXXXXXXXXXX
+ *   - "/tmp/" is a 5-byte prefix.
+ *   - N random characters follow, drawn independently and uniformly from
+ *     a 65-character alphabet (the POSIX portable filename character set)
+ *   - 1 byte for the NULL terminator.
+ * So: L_tmpnam = 5 + N + 1.
+ *
+ * Choosing N: we want the probability of two independently generated
+ * suffixes colliding to stay below a target threshold P, even after up to
+ * k calls to tmpnam() over the lifetime of a process.
+ *
+ * Let M = 65^N be the keyspace which is the total number of distinct
+ * N-character suffixes that can be generated (NOT the number actually
+ * generated; M is the size of the space they are drawn from).
+ *
+ * Among k calls, the number of distinct pairs of calls is:
+ *     C(k, 2) = k(k-1)/2  ~=  k^2 / 2      (approximation valid for large k)
+ *
+ * Each individual pair collides (picks the identical suffix) with
+ * probability 1/M, since each call draws independently and uniformly from
+ * the M possible suffixes.
+ *
+ * Treating pairwise collisions as approximately independent low-probability
+ * events, the probability that AT LEAST ONE collision occurs among all
+ * pairs is approximately the sum over all pairs of the per-pair probability:
+ *
+ *     P  ~=  (k^2 / 2) * (1 / M)  =  k^2 / (2M)
+ *
+ * This is the standard birthday-bound approximation.
+ *
+ * Solving for the keyspace required to keep P under a chosen target, given
+ * an assumed call-volume ceiling k:
+ *
+ *     M  >=  k^2 / (2P)
+ *
+ * Design inputs (stated, not borrowed):
+ *     k = 10^6   (one million calls: a generous upper bound on how many
+ *                 times a single long-running process could realistically
+ *                 call tmpnam() in its lifetime)
+ *     P = 10^-12 (one-in-a-trillion target collision probability)
+ *
+ * Required keyspace:
+ *     M >= (10^6)^2 / (2 * 10^-12) = 5 x 10^23
+ *
+ * Solving 65^N >= 5x10^23 for N:
+ *     N >= log_65(5x10^23) ~= 14 (round up)
+ *
+ * Therefore:
+ *     N         = 14
+ *     L_tmpnam  = 5 (prefix) + 14 (suffix) + 1 (NULL) = 20
+ */
+#ifndef L_tmpnam
+#define L_tmpnam 20
+#endif
+/*
----------------
kaladron wrote:

Similar here.

```c++
/*
 * TMP_MAX = 1,000,000 (10^6 calls per process).
 * Generous decimal call ceiling for the L_tmpnam guarantee;
 * provides a 6x safety margin below the 6.2M limit (P ~= 2.6 x 10^-14).
 */
```

I think should give people enough to reconstruct.  I don't think there's any need to mention glibc - we're deriving this independently.

https://github.com/llvm/llvm-project/pull/204901


More information about the libc-commits mailing list