cgmp

mpq sigsev when init after clear


The code(irrelevant parts removed)

void mpz_choose_ui(mpz_t rop,ul a,ul b){
    mpz_clear(rop);
    mpz_init(rop);
}

causes a segfault even though the mpz_t rop is cleared before init, gdb shows

0x00007ffff7da2c95 in __GI___libc_free (mem=0xffffffffffffffff) at malloc.c:3453
3453      if (chunk_is_mmapped (p))                       /* release mmapped memory. */

It seems like something is mapped even though mpz_clear was run before it.

minimum reproducable example is

void mpz_example(mpz_t rop){
    mpz_clear(rop);
    mpz_init(rop);
}
void example(){
    mpq_t tmp;
    mpz_t tmp2;
    mpz_t tmp3;
    mpz_example(tmp3);
}
int main(void)
{
    mpq_t rop;

    mpq_init(rop);
    example();
    return 0;
}

this reeks of use after free or something like that but everything is cleared then init-ed

yes they have to be 3 separate functions for some reason

tmp and tmp2 also have to be there for some reason


Solution

  • You're supposed to mpz_clear an initialized mpz_t when you're done with it, not before you start using it. mpz_clear frees the dynamically allocated storage an initialized mpz_t owns. When you clear it before you initialize it, you're trying to free uninitialized pointers.

    You can see in the documentation that usage is supposed to look like

    {
      mpz_t integ;
      mpz_init (integ);
      …
      mpz_add (integ, …);
      …
      mpz_sub (integ, …);
    
      /* Unless the program is about to exit, do ... */
      mpz_clear (integ);
    }
    

    with mpz_init to initialize the mpz_t and mpz_clear at the end to free allocated storage. mpz_clear does not go at the beginning.