Ben Pfaff wrote:
On Sat, Dec 29, 2018 at 09:22:17AM -0800, Paul Eggert wrote:
(Using ptrdiff_t is part of my campaign to prefer ptrdiff_t to size_t. While
we're at it, let's change the other size_t args to ptrdiff_t, but I
digress....)
Have you said anything about this campaign elsewhere? I'd like to hear
more.
I probably have, but it's easier for me to say something new afresh.
The C standard says that objects with size greater than PTRDIFF_MAX can cause
trouble, because subtracting pointers into these objects yields undefined
behavior if the resulting integer does not fit into ptrdiff_t. Worse, on many
popular systems (including GNU), even if (P - Q)'s value fits into ptrdiff_t, (P
- Q) can be calculated incorrectly if ((char *) P - (char *) Q) does not fit
into ptrdiff_t; although this behavior is contrary to the C standard it's such a
common problem that we cannot ignore it in portable code.
Because of this, C code should never allocate objects with size greater than
PTRDIFF_MAX unless it never does pointer subtraction with the result, and it's
generally simpler and more reliable if C code simply refuses to allocate such
objects under any circumstances. Gnulib started doing this a couple of years ago
with commit f3b846699de69b8e6a508396f7f778eb1e917a47, which causes
xalloc-oversized and related modules to reject attempts to create objects larger
than PTRDIFF_MAX bytes; this means many GNU applications are already safer.
(Emacs has a different way of enforcing the same restriction internally.) Also,
we are thinking of doing something similar with glibc's malloc/etc. functions in
the next glibc version, though this patch has not gone in yet and may have to
wait until the version after next.
As a result, C programs can now use either size_t or ptrdiff_t to store object
sizes, since no actual object can have more than min (SIZE_MAX, PTRDIFF_MAX)
bytes. Using signed types is better nowadays than using unsigned types, since
many platforms now check for signed integer overflow and this can catch many
bugs, some of them security-relevant, whereas unsigned arithmetic is well
defined to wrap around with no overflow check (something that can be quite
dangerous when doing size calculations). So, for reliability and security
reasons, C programs should now prefer ptrdiff_t to size_t when dealing with
object sizes.