unexpected MPZ_OVERFLOW

sisyphus sisyphus359 at proton.me
Sat Aug 8 07:14:47 CEST 2026


Hi,
The demo:
/****************************/
/* gmp_huge.c */
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>

int main (int argc, char *argv[]) {
mpz_t z;
unsigned long e = strtoul(argv[1], NULL, 0);
printf("size of long: %d\nsize of mp_size_t: %d\nGMP_NUMB_BITS: %d\nsize of int: %d\n",
sizeof(unsigned long), sizeof(mp_size_t), GMP_NUMB_BITS, sizeof(int));
printf("e: %x %u\n", e, e);

mpz_init_set_ui(z, 17);
printf("z set to 17\n");

mpz_mul_2exp(z, z, e);
printf("STILL ALIVE 1\n");

mpz_add_ui(z, z, 1);
printf("STILL ALIVE 2\n");

return 0;}
/****************************/

In Windows 11, I'm building gmp-6.3.0, using mingw-w64 ports of gcc-16.1.0 in the MSys2 shell.
I do both a 32-bit and 64-bit static builds.

With the 32-bit build, I can feed the above demo a value of 0xffffffbb, and the program runs to completion:

=============
32-bit build:
=============
D:\C>gcc -o huge32.exe gmp_huge.c -lgmp

D:\C>huge32 0xffffffbb
size of long: 4
size of mp_size_t: 4
GMP_NUMB_BITS: 32
size of int: 4
e: ffffffbb 4294967227
z set to 17
STILL ALIVE 1
STILL ALIVE 2

Oddly, with the 64-bit build, the maximum allowed value is lower - namely, 0xffffff7b.
Any more than that, and the 64-bit build hits the following MPFR_OVERFLOW in mpz/realloc.c, whereupon the program terminates silently:

if (sizeof (mp_size_t) == sizeof (int))
{
if (UNLIKELY (new_alloc > ULONG_MAX / GMP_NUMB_BITS))
MPZ_OVERFLOW;
}

For inputs in the range 0xffffff7c to 0xffffff7f (inclusive), it is the "mpz_add_ui(z, z, 1)" call that results in that MPZ_OVERFLOW.
For 0xffffff80 and higher, it's the "mpz_mul_2exp(z, z, e)" call that leads to the same MPFR_OVERFLOW.

=============
64-bit build:
=============
D:\C>set LIBRARY_PATH=D:\_64\msys_1610\1.0\local\lib

D:\C>gcc -o huge64.exe gmp_huge.c -lgmp

D:\C>huge64 0xffffff7b
size of long: 4
size of mp_size_t: 4
GMP_NUMB_BITS: 64
size of int: 4
e: ffffff7b 4294967163
z set to 17
STILL ALIVE 1
STILL ALIVE 2

D:\C>huge64 0xffffff7c
size of long: 4
size of mp_size_t: 4
GMP_NUMB_BITS: 64
size of int: 4
e: ffffff7c 4294967164
z set to 17
STILL ALIVE 1

D:\C>huge64 0xffffff7f
size of long: 4
size of mp_size_t: 4
GMP_NUMB_BITS: 64
size of int: 4
e: ffffff7f 4294967167
z set to 17
STILL ALIVE 1

D:\C>huge64 0xffffff80
size of long: 4
size of mp_size_t: 4
GMP_NUMB_BITS: 64
size of int: 4
e: ffffff80 4294967168
z set to 17

It seems odd to me that "new_alloc" should be able to take a maximum value on 32-bit builds that is double the maximum for a 64-bit build.
Is this all working as intended ?

CC'ing skirpichev at gmail.com and vincent at vinc17.net, both of whom provided valuable insight into this investigation.
(I understand that replies from gmp might not reach the first of those 2 addresses.)

Cheers,
Rob

Some other requested details:

$ ./config.guess
rocketlake-pc-mingw64

$ ./configfsf.guess
x86_64-pc-mingw64

$ uname -a
MINGW64_NT-10.0-26200 DESKTOP-88J497T 3.4.7.x86_64 2023-08-09 17:32 UTC x86_64 Msys

32-bit configure args:
$ ./configure --enable-static --disable-shared --enable-assembly ABI=32
(Also with --disable-assembly, which made no difference.)

64-bit configure args:
$ ./configure --enable-static --disable-shared --enable-assembly ABI=64
(Also with --disable-assembly, which made no difference.)

Sent with [Proton Mail](https://proton.me/mail/home) secure email.


More information about the gmp-bugs mailing list