No it isn't. The only guarantees you have about the size of long are that it is at least as large as (greater than or equal) a normal int. And a normal int is greater than or equal as big as a short.
C99 standard [1], §5.2.4.2.1 says otherwise. Int must acommodate at least 16 bits, long 32 bits, and long long 64 bits. C89 [2], §2.2.4.2 says the same thing but omits long long, so tweetnacl's u64 may not exist (this was the case with MSVC not too long ago).
Additionally, char is required to be at least 8 bits by the C standard, but tweetnacl assumes exactly 8. Some oddball architectures have larger character types, but POSIX mandates 8.
This code is attempting to be portable to C89, or why not just use C99's stdint.h? I don't believe your statement "C89 says the same thing," do you have a source to point to?
Do you have the section number in the latest freely available C99 working draft? The "Types" section (which 6.something in the draft) simply says what I said earlier about scalar rank. And 5.4.4.2.1 doesn't seem to exist in the draft.
Sorry, I mistyped the section number. Updated the parent comment with corrections and links.
I assume the intent of tweetnacl is to be C89-compatible, but due to the long long (and char, although that one's pretty pedantic) issue there's little guarantee of success.
Yes, TweetNaCl is. TweetNaCl's goal is to be auditable, not to be portable.
On the other hand, TinySSH actually includes a configuration mechanism to detect integer sizes, and modifies TweetNaCl accordingly, so TinySSH is not 32-bit/LLP64 only.
"Wait, this code is hard to understand and requires deep domain knowledge. Better nitpick the code style instead. Also, bikesheds should clearly be orange. Green is way too fishy."
I have domain knowledge and I've read a lot of code in my time. The style in use there is peculiar. That doesn't mean it is malicious or incorrect but it might make it easier to hide if it was.
stdint.h is C99 and while I'd love to believe that every C compiler is C99 capable by now, I don't know if that is actually the case.
Does stdint.h exist on Win32 these days?
Microsoft's poor support for standard C is no excuse not to use these types everywhere else and either define them yourself on windows or get stdint from boost, from one of the stdint.h replacements or <cstdint> from MSVC 2012.
* no qualifiers in parameter array declarators (`int x[static 10]`, etc.)
* no `restrict` keyword
* no compound literals
* no designated initializers
There's probably more.
On the web you'll find the same quote copy & pasted over and over saying that support for compound literals and designated initializers was supposedly added in VS2013, but it does not appear to be true. Either that, or I haven't found the hidden switch to enable it. By the way, C code still needs to be compiled as C++ to get anything beyond C89 to work, which should give you a clue as to how serious Microsoft is about C99.
What's true though is that stdbool.h was added. It's a start, I guess...
Comments
Is TweetNaCl deliberately 32-bit or LLP64 only? One of the first lines is
but on 64-bit LP64 systems (like Linux), long is 64-bits.See http://tweetnacl.cr.yp.to/20140427/tweetnacl.c
They seem to mask u32 values just fine everywhere, so u32 being larger than it has to is no problem.
ulong is as you know the smallest type that's always guaranteed to be at least 32 bits.
No it isn't. The only guarantees you have about the size of long are that it is at least as large as (greater than or equal) a normal int. And a normal int is greater than or equal as big as a short.
C99 standard [1], §5.2.4.2.1 says otherwise. Int must acommodate at least 16 bits, long 32 bits, and long long 64 bits. C89 [2], §2.2.4.2 says the same thing but omits long long, so tweetnacl's u64 may not exist (this was the case with MSVC not too long ago).
Additionally, char is required to be at least 8 bits by the C standard, but tweetnacl assumes exactly 8. Some oddball architectures have larger character types, but POSIX mandates 8.
[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
[2] http://nepsweb.co.uk/langstand/isoC/gordon/ansi-c89w.txt
This code is attempting to be portable to C89, or why not just use C99's stdint.h? I don't believe your statement "C89 says the same thing," do you have a source to point to?
Do you have the section number in the latest freely available C99 working draft? The "Types" section (which 6.something in the draft) simply says what I said earlier about scalar rank. And 5.4.4.2.1 doesn't seem to exist in the draft.
Sorry, I mistyped the section number. Updated the parent comment with corrections and links.
I assume the intent of tweetnacl is to be C89-compatible, but due to the long long (and char, although that one's pretty pedantic) issue there's little guarantee of success.
Huh, learned something new today, thanks. (For anyone following along, the C89 doc mentions the limits.h guidelines as well, search for "UINT_MAX".)
The name is a little confusing. The way u32 is used in TweetNaCl, it doesn't have to be exactly 32 bits, only at least 32 bits.
typedef uint_least32_t u32;
Yes, TweetNaCl is. TweetNaCl's goal is to be auditable, not to be portable.
On the other hand, TinySSH actually includes a configuration mechanism to detect integer sizes, and modifies TweetNaCl accordingly, so TinySSH is not 32-bit/LLP64 only.
Are you sure? The TweetNaCl paper says u32 is an unsigned >= 32-bit (see towards the end): http://tweetnacl.cr.yp.to/papers.html
I wonder why not just use stdint.h, it's got what you need. ..
[deleted]
Yes, I did see that post. The multiple statements per line thing is really fishy for a security critical piece of infrastructure.
This is essentially just a bikeshed.
"Wait, this code is hard to understand and requires deep domain knowledge. Better nitpick the code style instead. Also, bikesheds should clearly be orange. Green is way too fishy."
I have domain knowledge and I've read a lot of code in my time. The style in use there is peculiar. That doesn't mean it is malicious or incorrect but it might make it easier to hide if it was.
Sorry you don't see that.
stdint.h is C99 and while I'd love to believe that every C compiler is C99 capable by now, I don't know if that is actually the case. Does stdint.h exist on Win32 these days?
Microsoft's poor support for standard C is no excuse not to use these types everywhere else and either define them yourself on windows or get stdint from boost, from one of the stdint.h replacements or <cstdint> from MSVC 2012.
IMHO, of course.
I hate Microsoft as much as the next guy, but FYI, MSVC 2013 supports most of C99.
Maybe by Microsoft's definition of 'most'.
* no variable-length arrays
* no qualifiers in parameter array declarators (`int x[static 10]`, etc.)
* no `restrict` keyword
* no compound literals
* no designated initializers
There's probably more.
On the web you'll find the same quote copy & pasted over and over saying that support for compound literals and designated initializers was supposedly added in VS2013, but it does not appear to be true. Either that, or I haven't found the hidden switch to enable it. By the way, C code still needs to be compiled as C++ to get anything beyond C89 to work, which should give you a clue as to how serious Microsoft is about C99.
What's true though is that stdbool.h was added. It's a start, I guess...
That's good to hear, and maybe we can finally move on to more universal use of a 14 year old standard!