mpz_get_si: possible undefined behaviour? [Was: Micro-GMP]

Vincent Lefevre vincent at vinc17.net
Tue Dec 4 01:31:55 UTC 2018


On 2018-12-03 23:47:00 +0100, Marco Bodrato wrote:
> If LONG_MIN == -LONG_MAX-1, this step is correct.
> But, what about the LONG_MIN == -LONG_MAX case?
> The result is undefined, isn't it?

Yes.

> Which value we should actually return when the given mpz does not
> fit in the target type is not so well defined nor important,

One issue is that the function is poorly specified, if not buggy:

 -- Function: signed long int mpz_get_si (const mpz_t OP)
     If OP fits into a `signed long int' return the value of OP.
     Otherwise return the least significant part of OP, with the same
     sign as OP.

But on LONG_MAX + 1, mpz_get_si will give 0:

  if (size > 0)
    return zl & LONG_MAX;

while mathematically (and for mpz_sgn), 0 does not have the same sign
as a positive integer.

> but triggering an undefined behaviour seems a bad idea anyway.
> 
> 
> I'd suggest to substitute "-1" with "(LONG_MIN + LONG_MAX)", I mean
> something like:
> 
> return (LONG_MIN + LONG_MAX) -
>        (long) ((zp[0] - (-LONG_MAX - LONG_MIN)) & LONG_MAX);
> 
> 
> Comments about this analysis or better solutions?

I would write for clarity:

  long c = LONG_MIN + LONG_MAX;  /* -1 or 0 */
  /* ... */
  return c - (long) ((zp[0] - (-c)) & LONG_MAX);

and update the "Otherwise" case of the description, to say that the
returned value can be 0.

-- 
Vincent Lefèvre <vincent at vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


More information about the gmp-devel mailing list