That is a phenomenally stupid thing to do. There is legitimate need for reproducible pseudo-random sequences derived from a known random seed. If you break seeding that can't be done. This is how fuzz testing with generated inputs works.
That is a phenomenally stupid thing to do. There is legitimate need for reproducible pseudo-random sequences derived from a known random seed. If you break seeding that can't be done. This is how fuzz testing with generated inputs works.
Whereas lots of programs use rand as a source of general-purpose random numbers, but get the seeding wrong, and so suffer from various problems. This change fixes those programs.
[1] https://pubs.opengroup.org/onlinepubs/009696699/functions/ra...
Fucking things up for people who understand how PRNGs work just to fix things for people who don't seems backwards; things like this is why configure scripts take over a minute to run. I might be okay with the non-determinism in rand() if srand isn't ever called, but intentionally ignoring the stated intent of the program just pisses me off.
This is the path Go took for its math/rand library eventually: if you don't seed the RNG, it's a CSPRNG, but if you do seed it, it's deterministic.
However, there is lots of "advice" out there to seed your RNG with "random" values like the current time to make it "more secure" (and to be fair, in some cases, you may get sufficient entropy for the purpose at hand by doing this, but in most cases, you won't get enough and you'll spend it very fast). So a call to srand may indicate that you know what you're doing and want determinism and understand the consequences, but it doesn't necessarily mean that.
Good point. srand(time(NULL)) is a common, yet nondeterministic, seed. The caller clearly doesn't expect rand() to generate a particular sequence of numbers, so srand() could check whether the given seed looks like a time_t close to the current time() and, if it does, then use a proper CSPRNG instead.
> The following code defines a pair of functions that could be incorporated into applications wishing to ensure that the same sequence of numbers is generated across different machines.
And then gives code which does not use rand/srand. The intent of the spec is very clearly not for it to be portably reproducible.
Another example of when you need it, is games. I want to store in the game state, that on Day 32 of being in this cave, there is randomly a cache of diamonds if you mine the east wall. If I generate this random number dynamically, then I permit save-scumming behaviors which may distract from the artistic points of my game. So I basically want a random seed and a hash function, hashing (seed, day, activity, location, attempt_number) to see if something is successful.
Correct, but rand() / srand() aren't an effective way of providing for that need. The state of the RNG is process-global; it rapidly becomes nondeterministic in multithreaded applications, let alone if a library you're using calls rand() internally. And, as mentioned upthread, the algorithm is implementation-defined, and isn't guaranteed to remain the same over time.
Whereas, when you don't know what you're doing, the default should not be a footgun.
The appropriate solution is to not break anything and use tooling that flags use of banned symbols that can have negative safety or security implications.
In those cases, they provide deterministic operation under a different set of functions so nobody does anything as stupid as using deterministic RNG as encryption
I think it would have been better to remove rand and srand, and provide two replacement functions with different names, or require all users to pick one using a #define.