Subject: bug#8545: issues with recent doprnt-related changes

From: Paul Eggert <[email-masked]>
Date: Tue, 26 Apr 2011 13:25:21 -0700

On 04/25/11 06:37, Stefan Monnier wrote:
>> AFAIU, the
>> > preference to use signed is for those values that come from Lisp or go
>> > back to the Lisp level, which is not the case here.
> Mixing the two is what I find problematic, so if it's size_t all the
> way, that's OK.

Sorry, but I don't see the general principle.  Earlier, it was
thought that emacs_write should return a signed value, because there's
code like (emacs_write (...) != n) in fileio.c, where 'n' is
signed, and signed-versus-unsigned comparison is problematic.
I can certainly understand this point of view.

With doprnt returning size_t, though, we still have this problem.
In eval.c's verror we see this:

  size_t size_max =
    min (MOST_POSITIVE_FIXNUM, min (INT_MAX, SIZE_MAX - 1)) + 1;
  size_t used = ..., size = ...;
  ...
  while (1)
    {
      ...
      if (used < size - 1)
	break;
      if (size <= size_max / 2)
        size *= 2;
      else if (size < size_max)
        size = size_max;
      else
        break;  /* and leave the message truncated */
      ...
    }

Here, the code is carefully comparing a signed value
MOST_POSITIVE_FIXNUM to a possibly-different-width
unsigned value SIZE_MAX - 1, storing the result into an
unsigned variable, and using that unsigned variable.
This comparison happens to be safe, but one has to stare
at it a bit to make sure that the
unsigned-versus-signed comparison isn't bogus.  Why is
this unsigned-versus-signed comparison OK, but the one
with emacs_write problematic?

I'm not saying this to be difficult: I'm just trying to
understand the general principle here.

I thought the point of preferring signed was so that we
didn't have to worry about stuff like the above.  Also I assumed
the idea is that one should be able to compile GCC with -ftrapv
and catch overflow errors.  But if the above code is OK as-is,
then clearly I'm misunderstanding the overall goal here.