(fwiw, Android has someone working on adding this header to upstream LLVM right now, so hopefully it should come "for free" in llvm 18. what, if anything, to _do_ with it is another question though :-) )
On Mon, Aug 7, 2023 at 9:09 AM Lucian Popescu <lucian.popescu...@gmail.com> wrote: > > Hi, > > I noticed that some parts of OpenBSD use awkward techniques to detect > undefined behavior in arithmetic operations, for example: > > > static size_t > > poolBytesToAllocateFor(int blockSize) { > > /* Unprotected math would be: > > ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char); > > ** > > ** Detect overflow, avoiding _signed_ overflow undefined behavior > > ** For a + b * c we check b * c in isolation first, so that addition of > a > > ** on top has no chance of making us accept a small non-negative number > > */ > > const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */ > > > > if (blockSize <= 0) > > return 0; > > > > if (blockSize > (int)(INT_MAX / stretch)) > > return 0; > > > > { > > const int stretchedBlockSize = blockSize * (int)stretch; > > const int bytesToAllocate > > = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize); > > if (bytesToAllocate < 0) > > return 0; > > > > return (size_t)bytesToAllocate; > > } > > } > > The snippet was taken from lib/libexpat/lib/xmlparse.c > > This does not fully protect the code because bytesToAllocate might > overflow in the unsigned addition resulting in bytesToAllocate > 0. Note > that unsigned overflow is not undefined behavior but leads to unexpected > results. > > C23 solves this problem using <stdckdint.h> [1] which transforms the > above function into: > > > static size_t > > poolBytesToAllocateFor(int blockSize) { > > size_t add, mul; > > if (ckd_mul(&mul, blockSize, sizeof(XML_Char))) > > return 0; > > if (ckd_add(&add, mul, offsetof(BLOCK, s))) > > return 0; > > return add; > > } > > Is it worth bringing this functionality in OpenBSD? As a starting point > I was thinking that we can make use of __builtin_add_overflow et al. > when compiling with Clang. GCC is trickier to solve as the builtins were > implemented from version 5. > > Best Regards, > Lucian Popescu > > [1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2681.pdf