[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