3 ms·
You make it sound alot more complicated. Ignoring the library functions or stuff you can include from safe coding standard headers. You just do something like.
by maldev 3y ago
You make it sound alot more complicated. Ignoring the library functions or stuff you can include from safe coding standard headers. You just do something like.
BOOL AddOverflowUnsigned(BYTE* a, BYTE* b, INT32 sizea, INT32 sizeb)
{
BOOL IsMsb = PlatformIsMSB();
BOOL IsLsb = PlatformIsLSB();
//log error
if(!IsMsb && !IsLsb)
return FALSE;
//Early out for overflow. Assuming
if(sizea == sizeb && PlatformIsMSB())
{
BOOL AMsb = (a >> ((sizea * PlatformByteSize()) - 1)) & 1;
BOOL BMsb = (b >> ((sizeb * PlatformByteSize()) - 1)) & 1;
if(AMSB && BMsb)
{
//We overflow, early out.
return FALSE;
}
else if(sizea == sizeb && PlatformIsLSB())
//Code here.
//We add using bitwise operators so we can do it on any size.
//SUM = A XOR B XOR CARRY, return in A
//Impliment algo here.
return TRUE;
}
int main()
{
UINT64 a = 69;
UINT64 b = 420;
if(sizeof(a) !
return AddOverflowUnsinged(&a, &b, sizeof(a), sizeof(b));
}
But they have this in the STD now and also all the secure coding libs have this in it's header as a basic function. There's also the easier implementation of just adding a check to see if it will overflow, rather than add in the function.
You also only have a few you can hardcode if you don't do it generic, since all will go back to the primitives of uint8, uint16 ....
- mananaysiempre 3y agoThis is OK as a fallback, even if it's not at all strictly compliant (the standard still allows PDP or Honeywell endian and padding bits wherever). As the main option it's extremely silly, though, when the entirety of the function on e.g. x86-64 could be (using the GCC signature but MS calling convention and syntax for according to your apparent preference) ; bool add_overflowll(long long x, long long y, long long *result) add_overflowll PROC add rcx, rdx seto eax mov qword ptr [r8], rcx ret add_overflowll ENDP for a total of no loops, no conditional branches, and three instructions with no branches at all when inlined (not shown because I don't remember the MS inline assembly syntax). Why check beforehand when the CPU does the check for you on every arithmetic operation and all you need to do is to ask it for the result? (Unless your CPU is RISC-V because RISC-V.) And of course the newfangled standard functions are size-dependent (more like mine than yours), so either you still need _Generic or essentially equivalent compiler-specific magic, or you have to introduce an ABI dependency on which integer type your ptrdiff_t or ssize_t or off_t or whatever typedef you got from a random place in a library or OS header actually ends up being.
- maldev 3y agoThat relies on architecture things that arn't in C. and that's why I say "ignoring the library functions or stuff you can include from safe coding standard headers. ". Of course you can do an intrinsic or whatever, and that's better obviously. But I wanted to show how easy it is to write a platform independent function to do this from raw C.
- Joker_vD 3y agoFirst of all, you forgot to return the actual sum from the function. Second, original add_overflow-style functions support arbitrary expressions as input arguments, not just pointers to l-values. And third, there is no way all this stuff is going to get optimized down to inlined add rdi, rsi setc eax mov [rdx], rdi
- maldev 3y agoReturn value is returned in a, it returns true or false on whether overflow happened. And you're assuming that you're on x86_64. You can't do that in C. C is platform independent. Which is why I said you can use one of the functions or intrinsics, and writing it yourself is bad, but still easy.