| ▲ | strenholme 3 hours ago | |||||||||||||||||||||||||||||||||||||
I recently had a heated but productive discussion about undefined behavior here. As per the linked article: “There are currently about 100 instances of undefined behavior in the C standard, but the in-progress C2y draft has removed 45 of them.” I wonder how they handle the specific case of uninitialized but allocated memory. Let’s look at something which will result in undefined behavior in C99: [1]
The key part of the above brick of code is this:
Here, we see that q[0] is an allocated but undefined byte. As per C99, this results in undefined behavior, however 20 years ago this was a good trick to get kinda-randomish bytes to use as a possible entropy source.Someone claimed that the above brick of code will compile in newer versions of clang such that, since the complex cryptographic pseudo random number generator code depends on uninitialized but allocated memory, the entire cryptographic operation isn’t performed. So I tested it against multiple versions of GCC and clang; I also tested it against TCC for good measure. In all cases, with all levels of optimization, the cryptographic routine ran. I even ran it against clang 23. In cygwin, it was a randomish but consistent byte (except for clang at a higher level of optimization, at which point the uninitialized byte had a value of 0); in Ubuntu 26, the uninitialized memory consistently had a value of 0 (in tcc/gcc/clang). I am hoping the up and coming C2y spec has very clearly defined behavior when using unintialized memory (ideally where it will work but the bytes can have any values). Naturally, I have updated my code to no longer use uninitialized memory as a source of entropy. 20 years ago, MacOS didn’t support clock_gettime() with nanosecond resolution, so that wasn’t a portable way to get pseudo-random bits; these days clock_gettime() is universal across modern development environments, and it provides pretty good entropy (along with using /dev/urandom in *NIX, which isn’t in POSIX but is widely supported, as well as CryptGenRandom() in the legacy Win32 port). [2] [1] Said person said the appendices to C99 aren’t authoritative, but if something is in the spec, including in the appendices, it’s authoritative. [2] I don’t blindly trust /dev/urandom to always make really hard to guess pseudo-random bits, because my code is open source, and, as such, doesn’t just compile in Linux. It often times will be compiled in embedded systems, and even Linux has had at times issues with /dev/urandom on Raspberry Pis. [3] I would also like to see uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, and int64_t mandated. They exist in C99, but aren’t mandated, even though every real world compiler from this century supports all of the above types. Yes, I know about _BitInt(8/16/32/64/128/etc.) but a compiler from 2004—and yes I still use one to make win32 binaries—doesn’t support these new C23 datatypes. | ||||||||||||||||||||||||||||||||||||||
| ▲ | jcranmer 3 hours ago | parent | next [-] | |||||||||||||||||||||||||||||||||||||
> [1] Said person said the appendices to C99 aren’t authoritative, but if something is in the spec, including in the appendices, it’s authoritative. That's not true. There is a difference between normative text and informative text. Informative text is not authoritative, and you were citing an appendix that is labeled as informative. > I am hoping the up and coming C2y spec has very clearly defined behavior when using unintialized memory (ideally where it will work but the bytes can have any values). It won't. Uninitialized memory can't have "very clearly defined behavior" without breaking essentially every single implementation, and WG14 is very loth to break existing implementations. | ||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||
| ▲ | afdbcreid 3 hours ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
It is quite hard to come with a reliable example, but (https://c.godbolt.org/z/56bfYszEb):
This compiles into `exit(1)` in Clang under -O3. | ||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||
| ▲ | fragmede 3 hours ago | parent | prev [-] | |||||||||||||||||||||||||||||||||||||
Interesting. x86_64 has RDRAND for entropy (and RDSEED to seed). Oh I guess there's also ARM these days but I bet they got one too. | ||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||