cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

[SUGGESTION] Prevent signed overflow/underflow & unsigned carry

Open bluetarpmedia opened this issue 1 year ago • 3 comments

Suggestion As presented at CppCon 23, cppfront could transform integer arithmetic operations so that they trap/terminate on overflow, underflow or carry. This is a similar solution to my #220 suggestion.

A Cpp2 expression like this:

a + b

would lower to Cpp1 like this:

cpp2::checked_add(a, b)

For the situation where the programmer wants the Cpp1 behaviour (e.g. hashing, or performance where the programmer takes on the risk of overflow etc), Cpp2 could introduce new operators (like Swift has):

a &+ b

which would lower to Cpp1:

a + b

The cpp2::checked_add function (and others for subtract, mul) could be implemented using compiler builtins or intrinsics, such as:

  • __builtin_add_overflow
  • _addcarry_u32
  • C23's ckd_add

or failing that, a manual implementation fallback option.

These builtins/intrinsics generally work like this:

int a = -1073741826;
int b = -1073741826;
int result = 0;
if (__builtin_add_overflow(a, b, &result)) {
    std::terminate();
}

// `result` is OK

Will your feature suggestion eliminate X% of security vulnerabilities of a given kind in current C++ code?

Yes, there are many examples. See: https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=integer+overflow

Will your feature suggestion automate or eliminate X% of current C++ guidance literature?

Yes, see core guidelines:

  • ES.103: Don’t overflow
  • ES.104: Don’t underflow

Describe alternatives you've considered.

Instead of introducing the Swift-like operators to opt-out of the safe arithmetic (e.g. &+), Cpp2 could have explicit functions like Rust:

  • wrapping_add
  • checked_add

However, the new operators allow for terser code closer to the original.

bluetarpmedia avatar Oct 03 '23 00:10 bluetarpmedia

Thanks! It looks like GCC's intrinsics are supported on Clang, as usual, for all the versions of GCC and Clang that cppfront supports. Also Intel appears to support them all.

It's only just been added to MSVC though and using a different set of names.

hsutter avatar Oct 09 '23 00:10 hsutter

The CERT C coding standard has implementations that could be used as the fallback option for compilers which don't have intrinsics:

signed overflow unsigned wrap

Re MSVC, if targeting Windows 7+ or Server 2008 R2+ then the Intsafe.h header can be used, which provides functions like IntAdd, LongLongAdd, etc.

Also, for unsigned wrap, MSVC supports Intel intrinsics like _addcarry_u32.

bluetarpmedia avatar Oct 10 '23 03:10 bluetarpmedia

Is this worth doing in Cpp2? As soon as you wrap integer types in Cpp1 types, you no longer benefit.

a &+ b isn't needed. You just need a or b to not be a fundamental type. For example, Cpp2 could provide cpp1_unsigned as an alias for some unsigned wrapper. That wouldn't be picked up by the special cpp2::checked_add(a, b) overload.

From https://github.com/hsutter/cppfront/discussions/649#discussioncomment-6869577:

Disclaimer: I dislike even mentioning a gross idea like wrapping fundamental types, it just screams "overhead!" But for the sake of discussion...

JohelEGP avatar Oct 30 '23 15:10 JohelEGP