Invalid read in mpz_sub
Miha Marolt
miham at beyondsemi.com
Wed Apr 6 11:58:41 UTC 2016
Hello,
In some cases a previously freed memory is read inside the mpz_sub function. Here is
an example program that demonstrates the problem:
```
#include <gmp.h>
typedef struct {
mpz_t a;
mpz_t b;
} pair_t;
void pair_sub(pair_t *out, pair_t in)
{
// Description of the problem:
// Given the arguments &x and x (see main function) out->a->_mp_d and
// in.a->_mp_d point to the same memory.
// Inside the mpz_sub function out->a->_mp_d gets reallocated, but in.a->_mp_d
// stays the same (now pointing to invalid memory) because in.a and out->a are
//not the same object.
mpz_sub(out->a, in.b, in.a);
}
int main(void)
{
mpz_t a, b;
mpz_init_set_str(a, "10", 0);
mpz_init_set_str(b, "20", 0);
pair_t x;
mpz_inits(x.a, x.b, NULL);
mpz_set(x.a, a); // x.a: _mp_size == _mp_alloc.
mpz_set(x.b, b); // x.b: _mp_size == _mp_alloc.
pair_sub(&x, x);
mpz_clears(a, b, x.a, x.b, NULL);
}
```
Compile it with `$ gcc main.c -o main -lgmp` and run under Valgrind with
`$ valgrind --leak-check=full --show-leak-kinds=all ./main`. Valgrind reports
invalid reads:
```
==14174== Memcheck, a memory error detector
==14174== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==14174== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==14174== Command: ./e_bug_mpz_sub
==14174==
==14174== Invalid read of size 8
==14174== at 0x4E57AB0: UnknownInlinedFun (gmp.h:2155)
==14174== by 0x4E57AB0: __gmpz_sub (aors.h:96)
==14174== by 0x400808: pair_sub (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174== by 0x4008A2: main (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174== Address 0x546e180 is 0 bytes inside a block of size 8 free'd
==14174== at 0x4C2AB8B: realloc (vg_replace_malloc.c:785)
==14174== by 0x4E41803: __gmp_default_reallocate (memory.c:102)
==14174== by 0x4E560C9: __gmpz_realloc (realloc.c:61)
==14174== by 0x4E57BA0: __gmpz_sub (aors.h:76)
==14174== by 0x400808: pair_sub (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174== by 0x4008A2: main (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174== Block was alloc'd at
==14174== at 0x4C28BF6: malloc (vg_replace_malloc.c:299)
==14174== by 0x4E417B8: __gmp_default_allocate (memory.c:54)
==14174== by 0x4E50327: __gmpz_init (init.c:38)
==14174== by 0x4E50429: __gmpz_inits (inits.c:45)
==14174== by 0x400860: main (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174==
==14174== Invalid read of size 8
==14174== at 0x4E5C69E: __gmpn_sub_n (tmp-sub_n.s:116)
==14174== by 0x4E57ADD: __gmpz_sub (aors.h:106)
==14174== by 0x400808: pair_sub (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174== by 0x4008A2: main (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174== Address 0x546e180 is 0 bytes inside a block of size 8 free'd
==14174== at 0x4C2AB8B: realloc (vg_replace_malloc.c:785)
==14174== by 0x4E41803: __gmp_default_reallocate (memory.c:102)
==14174== by 0x4E560C9: __gmpz_realloc (realloc.c:61)
==14174== by 0x4E57BA0: __gmpz_sub (aors.h:76)
==14174== by 0x400808: pair_sub (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174== by 0x4008A2: main (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174== Block was alloc'd at
==14174== at 0x4C28BF6: malloc (vg_replace_malloc.c:299)
==14174== by 0x4E417B8: __gmp_default_allocate (memory.c:54)
==14174== by 0x4E50327: __gmpz_init (init.c:38)
==14174== by 0x4E50429: __gmpz_inits (inits.c:45)
==14174== by 0x400860: main (in /home/miha/coding/ssike/src/examples/e_bug_mpz_sub)
==14174==
==14174==
==14174== HEAP SUMMARY:
==14174== in use at exit: 0 bytes in 0 blocks
==14174== total heap usage: 7 allocs, 7 frees, 80 bytes allocated
==14174==
==14174== All heap blocks were freed -- no leaks are possible
==14174==
==14174== For counts of detected and suppressed errors, rerun with: -v
==14174== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
```
Versions of used components:
* GMP 6.0.0 from the Fedora 23 repositories.
* GCC 5.3.1 from the Fedora 23 repositories.
Verbose GCC version:
```
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 5.3.1 20151207 (Red Hat 5.3.1-2) (GCC)
```
Output of `$ uname -a`:
```
Linux ariel 4.4.6-300.fc23.x86_64 #1 SMP Wed Mar 16 22:10:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
```
Output of `$ ./config.guess`:
```
nehalem-pc-linux-gnu
```
Best regards,
Miha Marolt
More information about the gmp-bugs
mailing list