4 ms·
I thought these issues are obvious by now. Some typical points to consider: 1) Never store a length as an int, unsigned, long, etc. Use size_t (or ssize_t) in
by vardump 10y ago
I thought these issues are obvious by now.
Some typical points to consider:
1) Never store a length as an int, unsigned, long, etc. Use size_t (or ssize_t) instead.
2) Never store a pointer as an int, unsigned, long, etc. Use uintptr_t (or intptr_t). ptrdiff_t is the type to use for pointer differencing.
3) When comparing or casting to a signed type, watch out for sign extension. For example (short) -1 (0xffff) becomes 2^32-1 (0xffffffff) when casted to uint32_t. Remember char is usually a signed type.
4) Some legacy library functions return int, which is a signed 32-bit value in Windows and Linux (remember point 3). Watch out for these cases. For example don't use ftell and check s[n]printf return value.
- tormeh 10y agoDoes Rust fix this, or is this mess still necessary?
- Coding_Cat 10y agoI don't now if it fixes it per se, but it does make it harder to mess up. For example, it does not automatically convert between sizes (usize) and unsigned integers (u64).
- jibsen 10y agoIt's worth noting that ssize_t is a POSIX type, and is only guaranteed to have the range [-1, SSIZE_MAX] (basically a size type with one error value) [1]. If you need negative sizes, then ptrdiff_t is perhaps better. [1]: http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/types.h.html http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/...
- vardump 10y agoThanks for the correction! > only guaranteed to have the range [-1, SSIZE_MAX] Oh, that's a weird type. I wonder if any compiler implementation encodes it with -1 bias, so that all bits 0 means "-1". It could cause a disaster if/when ssize_t is encoded as anything else but standard twos complement signed number...
- colejohnson66 10y agoI'd assume it's just an unsigned number with 0xFF... representing -1. So counting would go (assuming 8 bits) 0xFC SSIZE_MAX - 2 0xFD SSIZE_MAX - 1 0xFE SIZE_MAX 0xFF -1 That makes more sense to me than a bias that the compiler would have to know about.
- sebcat 10y agolibcurl recently got CVE-2016-7167 for 1: https://curl.haxx.se/docs/adv_20160914.html https://curl.haxx.se/docs/adv_20160914.html "The provided string length arguments were not properly checked and due to arithmetic in the functions, passing in the length 0xffffffff (2^32-1 or UINT_MAX or even just -1) would end up causing an allocation of zero bytes of heap memory that curl would attempt to write gigabytes of data into."
- lomnakkus 10y ago> I thought these issues are obvious by now. Obvious (well, relatively), but alas non-trivial to fix in a codebase of even moderate size. (5k+ LoC, let's say) Implicit integral conversions are one of the worst things ever foisted upon the programming world... and that's saying something (given the existence of NULL). Well, that and the whole size_t == unsigned <whatever> thing[1]. [1] I can certainly agree that it was useful when it was introduced because it actually doubled your addressable storage in a practical way, but does any existing machine address even close to 64-bit? For context: 60-bits of addressability is ~1000PB.
- legulere 10y ago> by now The only problem is that there's lots of software written before those types even existed, and even today people might learn a bad style from old code. The problem is that compilers hardly compel one to use a good coding style.
- cestith 10y agoRegarding char, remember it's best to always specify because "usually" is still not "always".
- winter_blue 10y ago> For example (short) -1 (0xffff) becomes 2^32-1 (0xffffffff) when casted to uint32_t. Ideally the compiler would do a check during a conversion from a negative signed integer to unsigned integer, and set a flag or throw some sort of exception. Hopefully future languages (e.g. Rust) learn from this.