NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bin/47301: Miscompilation by bundled GCC
>Number: 47301
>Category: bin
>Synopsis: Miscompilation by bundled GCC
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Dec 09 16:00:01 +0000 2012
>Originator: Torbjorn Granlund
>Release: NetBSD 6.0
>Organization:
KTH, Sweden
>Environment:
NetBSD slug.gmplib.org 6.0 NetBSD 6.0 (GENERIC) vax
>Description:
The current GMP source code is miscompiled by /usr/bin/gcc.
The result is crashes in n-factorial computations.
>How-To-Repeat:
Either get ftp://gmplib.org/pub/snapshot/gmp-5.1.0-RC1.tar.xz
and isolate the problem of oddfac_1.c in mpz_oddfac_1. Expect a crash
for n <= ODD_FACTORIAL_TABLE_LIMIT.
I have created a smaller test case which I have not executed, but
where it is very obvious that there is a miscompile.
Source:
typedef unsigned long int mp_limb_t;
typedef struct
{
int _mp_alloc;
int _mp_size;
mp_limb_t *_mp_d;
} __mpz_struct;
typedef __mpz_struct mpz_t[1];
typedef mp_limb_t * mp_ptr;
typedef long int mp_size_t;
typedef __mpz_struct *mpz_ptr;
extern const mp_limb_t __gmp_oddfac_table[];
extern const mp_limb_t __gmp_odd2fac_table[];
static mp_limb_t id_to_n (mp_limb_t id) { return id*3+1+(id&1); }
static mp_limb_t n_to_bit (mp_limb_t n) { return ((n-5)|1)/3U; }
static mp_limb_t limb_apprsqrt (mp_limb_t x) { return x; }
static void
mpz_2multiswing_1 (mpz_ptr x, mp_limb_t n, mp_ptr sieve, mp_ptr factors)
{
mp_limb_t prod, max_prod;
mp_size_t j;
j = 0;
prod = -(n & 1);
n &= ~1L;
prod = (prod & n) + 1;
max_prod = ((~ ((mp_limb_t) (0))) >> 0) / (n-1);
mp_limb_t __q, __prime;
__prime = 3;
if (prod > max_prod)
{
factors[j++] = prod;
prod = 1;
}
__q = n;
do {
__q /= __prime;
if ((__q & 1) != 0)
prod *= __prime;
} while (__q >= __prime);
mp_limb_t s;
mp_limb_t prime;
s = limb_apprsqrt(n);
s = n_to_bit (s);
mp_limb_t __mask, __index, __max_i, __i;
__i = n_to_bit (5);
__index = __i / 32;
__mask = ((mp_limb_t) 1L) << (__i % 32);
__i += 0;
__max_i = s;
do {
++__i;
if ((sieve[__index] & __mask) == 0)
{
prime = id_to_n(__i);
mp_limb_t __q, __prime;
__prime = prime;
if (prod > max_prod)
{
factors[j++] = prod;
prod = 1;
}
__q = n;
do {
__q /= __prime;
if ((__q & 1) != 0)
prod *= __prime;
} while (__q >= __prime);
}
__mask = __mask << 1 | __mask >> 31;
__index += __mask & 1;
} while (__i <= __max_i);
s++;
if (j != 0)
{
factors[j++] = prod;
__gmpz_prodlimbs (x, factors, j);
}
}
void
miscompiled_function (mpz_ptr x, mp_limb_t n, unsigned flag)
{
if (n <= 16)
{
/* This is miscompiled. The store address is completely bogus. */
mp_limb_t xxx = __gmp_oddfac_table[n];
(x->_mp_d)[0] = xxx;
(x->_mp_size) = 1;
}
else
{
unsigned s;
mp_ptr factors;
mp_limb_t tn;
mp_limb_t prod, max_prod, i;
mp_size_t j;
s = 0;
for (tn = n; tn >= 400; s++)
tn >>= 1;
j = 0;
factors = (mp_limb_t *) __builtin_alloca(199 * sizeof (mp_limb_t));
prod = 1;
max_prod = 98723491;
do {
i = 21;
factors[j++] = 0x27065f73L;
do {
if (prod > max_prod)
{
factors[j++] = prod;
prod = i;
}
else
prod *= i;
i += 2;
} while (i <= tn);
max_prod <<= 1;
tn >>= 1;
} while (tn > 20);
factors[j++] = prod;
factors[j++] = __gmp_odd2fac_table[(tn - 1) >> 1];
factors[j++] = __gmp_oddfac_table[tn >> 1];
__gmpz_prodlimbs (x, factors, j);
if (s != 0)
{
mpz_t mswing;
mp_ptr sieve;
mp_size_t size;
size = n / (32 - 0) + 4;
mpz_ptr __x = mswing;
__x->_mp_alloc = size;
__x->_mp_d = (mp_limb_t *) __builtin_alloca(size * sizeof
(mp_limb_t));
sieve = (mswing->_mp_d) + size / 2 + 1;
size = (__gmp_primesieve (sieve, n - 1) + 1) / n + 1;
factors = (mp_limb_t *) __builtin_alloca(size * sizeof (mp_limb_t));
do
{
mp_ptr square, px;
mp_size_t nx, ns;
mp_limb_t cy;
s--;
mpz_2multiswing_1 (mswing, n >> s, sieve, factors);
nx = (x->_mp_size);
ns = (mswing->_mp_size);
nx = size + ns;
px = (nx) > (x->_mp_alloc) != 0 ? (mp_ptr) __gmpz_realloc(x,nx) :
x->_mp_d;
cy = __gmpn_mul (px, square, size, mswing->_mp_d, ns);
(x->_mp_size) = nx - (cy == 0);
}
while (s != 0);
}
}
}
Compile with the default compiler (claimed as 4.1.3) using -O
and no other flags. This code is generated for the first part
of miscompiled_function:
miscompiled_function:
.word 0xfc0
subl2 $60,%sp
cmpl 8(%ap),$16
jlequ .L4
cmpl 8(%ap),$399
jgtru .L6
movl 8(%ap),%r4
clrl -60(%fp)
jbr .L8
.L4:
movl 8(%ap),%r0
movl __gmp_oddfac_table[%r0],*8(%r0) BAD
movl 4(%ap),%r1
movl $1,4(%r1)
ret
The line annotated BAD stores in a completely invalid place,
related to the (non-pointer!) argument n. Note that the source
operand is valud, using n properly.
It is fairly easy to make the compiler generate valid code by
making innocent changes to this file.
>Fix:
I have not made any attempt at fixing this compiler bug, since
I feel gcc 4.1 is obsolete.
If I were you, I'd upgrade to a current GCC version. I notice
that your fear of GPL 3 seems limited given that the binutils
of this install is quite new, so GPL 3 must not be a valid
reason for staying obsolete with GCC.
Home |
Main Index |
Thread Index |
Old Index