isocpp / isocpp/CppCoreGuidelines
Approach for narrow<T> is not correct
@neilmacintosh is already working on this.
Since May 14, 2018.
- Dominant language
- CSS
- Stars
- 45.3k
- Forks
- 5.6k
- PR merge metrics
- No merged PRs in 30d
Description
In section ES.49: If you must use a cast, use a named cast, there is the following statement:
gsl::narrow // narrow(x) is static_cast(x) if static_cast(x) == x or it throws narrowing_error
The following sample illustrates the problem -
unsigned int x = 0xffffffff;
if(static_cast< int >(x) == x)
cout << "This is safe";
The problem here is that in order to do the comparison, we cast the int back to unsigned int, and because we didn't change the bit pattern, this will evaluate as true. I haven't had the time today to apply this code to the SafeInt test suite (https://github.com/dcleblanc/SafeInt), but other conversions should also fail.
In addition, this would throw a false negative in the case of a cast to bool for all but inputs of 0 or 1.
Another problem in the code is this:
size_t y = something();
unsigned int x = narrow(y);
Assuming a 32-bit int and a 32-bit memory space, this check would still have a comparison, when it should optimize away. In an x64 compile, we do need the check.
Also, there seems to be a design issue here - this seems to assume that the only problem is narrowing. Signed-unsigned mismatch can also cause problems, so while converting a negative signed short to an unsigned long may not be narrowing, it can be problematic.
I'd be happy to extract the casting portion of SafeInt to fix this.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.