[Bug target/81801] [PATCH] Difference of two pointers generates signed overflow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81801 Andrew Pinski changed: What|Removed |Added Resolution|--- |DUPLICATE Status|UNCONFIRMED |RESOLVED --- Comment #5 from Andrew Pinski --- Dup of bug 13421. *** This bug has been marked as a duplicate of bug 13421 ***
[Bug target/81801] [PATCH] Difference of two pointers generates signed overflow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81801 --- Comment #4 from joseph at codesourcery dot com --- On Fri, 11 Aug 2017, oss at malat dot biz wrote: > One could solve it by dividing both pointers by the size before the > subtraction, but that would make the operation more expensive. See also what I said in bug 67999 comment 24. The combination (subtract to produce a ptrdiff_t result, with modulo arithmetic on overflow, then divide in ptrdiff_t) isn't correct for objects too large in bytes for ptrdiff_t. But the following should be correct: right shift (logical) both pointers for the power-of-2 factor in what you are dividing by, subtract (modulo), multiply (modulo) by the (mod 2^n) reciprocal of the odd part of what you are dividing by, interpret the result as signed. It's less efficient than code sequences that only work for objects less than half the address space, and such large objects can never work if you do pointer subtraction of pointers to char that are too far apart to be represented in ptrdiff_t. I think it makes most sense to disallow such large objects properly (including in malloc and mmap), but an option to support pointer subtraction in them would not be ridiculous.
[Bug target/81801] [PATCH] Difference of two pointers generates signed overflow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81801 --- Comment #3 from Petr Malat --- After reading the related part of the standard (actually, N1570 draft), I'm not so sure about this. The semantics section in 6.5.6 says pointers have to be from the same object and also the result must fit into the ptrdiff_t, which range is [PTRDIFF_MIN, PTRDIFF_MAX], which has to be equal or larger than [-65535, 65535]. So, theoretically it would be fine to use a shorter type for that, however there is still a problem if the calculation is done as it is now for larger objects as the difference is computed first at bytes and divided later by the object size, so the overflow can still happen even the result fits in [PTRDIFF_MIN, PTRDIFF_MAX]. One could solve it by dividing both pointers by the size before the subtraction, but that would make the operation more expensive.
[Bug target/81801] [PATCH] Difference of two pointers generates signed overflow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81801 --- Comment #2 from Andrew Pinski --- Related to PR 80998.
[Bug target/81801] [PATCH] Difference of two pointers generates signed overflow
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81801 Andrew Pinski changed: What|Removed |Added Target||32bit target Component|c |target --- Comment #1 from Andrew Pinski --- Actually it is worse than you think. The problem is __PTRDIFF_TYPE__ is defined incorrectly if pointers can span across the sign bit (32bit). There is whole thread about this on gcc@. The C/C++ language defines ptrdiff_t as a type which can be used two take a difference of any two valid pointers and get a signed difference. In the case here 0x8002000f-0x0001000f should actually return a signed integer that represents the space between those two pointers.