I was digging into code of flatbuffers and it does seem to me that there is undefined behavior in the core library. But I just can't believe it is there (and it seems to work in some usecases)...
I'd highly appreciate if somebody verifies my way of thinking/shows me that I missed something :)
difference_type operator-(const VectorIterator &other) const {
return (data_ - other.data_) / element_stride;
}
My rationale, why I think it is UB:
difference_type == std::ptrdiff_t which is based on standard Signed ["something" >= 16b] (https://en.cppreference.com/w/cpp/types/ptrdiff_t)
Let's expect that the first parenthesis end up negative (which should be valid usecase)
Now when I assume the ptrdiff_t is <= size_t:
We get to:
- ptrdiff_t retval = (uint8_t* - uint8_t*)/size_t
pointer arithmetics also end up as ptrdiff_t. So we are at:
- ptrdiff_t retval = ptrdiff_t/size_t
This leads me to:
- Signed = Signed/Unsigned
And based on standard (8/11.5.3) we get the first operand of divison promoted to Unsigned: The standard snippet
- the result will end up as "something positive and huge" as the negative number got promoted to huge unsigned one
Now lets assume ptrdiff_t is > size_t
- pretty much same steps apply, except the last one:
- based on standard (8/11.5.4), the second operand of division get promoted to signed number of bigger bitsize
- this leads to return value to be (the intuitive) negative number that says distance between the two VectorIterators.
- pretty much same steps apply, except the last one:
So I see there 2 possible outcomes of the operator-, both complying with the standard requirements, based on ptrdiff_t implementation by specific compiler.
Thanks!
return, so huge positive value becomes normal negative one again.element_stridetoptrdiff_t?