Blame tests/memory.c

Packit 5c3484
/* Memory allocation used during tests.
Packit 5c3484
Packit 5c3484
Copyright 2001, 2002, 2007, 2013 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library test suite.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is free software; you can redistribute it
Packit 5c3484
and/or modify it under the terms of the GNU General Public License as
Packit 5c3484
published by the Free Software Foundation; either version 3 of the License,
Packit 5c3484
or (at your option) any later version.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is distributed in the hope that it will be
Packit 5c3484
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5c3484
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit 5c3484
Public License for more details.
Packit 5c3484
Packit 5c3484
You should have received a copy of the GNU General Public License along with
Packit 5c3484
the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
#include <stdio.h>
Packit 5c3484
#include <stdlib.h>		/* for abort */
Packit 5c3484
#include <string.h>		/* for memcpy, memcmp */
Packit 5c3484
#include "gmp.h"
Packit 5c3484
#include "gmp-impl.h"
Packit 5c3484
#include "tests.h"
Packit 5c3484
Packit 5c3484
#if GMP_LIMB_BITS == 64
Packit 5c3484
#define PATTERN1 CNST_LIMB(0xcafebabedeadbeef)
Packit 5c3484
#define PATTERN2 CNST_LIMB(0xabacadabaedeedab)
Packit 5c3484
#else
Packit 5c3484
#define PATTERN1 CNST_LIMB(0xcafebabe)
Packit 5c3484
#define PATTERN2 CNST_LIMB(0xdeadbeef)
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
#if HAVE_INTPTR_T
Packit 5c3484
#define PTRLIMB(p)  ((mp_limb_t) (intptr_t) p)
Packit 5c3484
#else
Packit 5c3484
#define PTRLIMB(p)  ((mp_limb_t) (size_t) p)
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
/* Each block allocated is a separate malloc, for the benefit of a redzoning
Packit 5c3484
   malloc debugger during development or when bug hunting.
Packit 5c3484
Packit 5c3484
   Sizes passed when reallocating or freeing are checked (the default
Packit 5c3484
   routines don't care about these).
Packit 5c3484
Packit 5c3484
   Memory leaks are checked by requiring that all blocks have been freed
Packit 5c3484
   when tests_memory_end() is called.  Test programs must be sure to have
Packit 5c3484
   "clear"s for all temporary variables used.  */
Packit 5c3484
Packit 5c3484
Packit 5c3484
struct header {
Packit 5c3484
  void           *ptr;
Packit 5c3484
  size_t         size;
Packit 5c3484
  struct header  *next;
Packit 5c3484
};
Packit 5c3484
Packit 5c3484
struct header  *tests_memory_list = NULL;
Packit 5c3484
Packit 5c3484
/* Return a pointer to a pointer to the found block (so it can be updated
Packit 5c3484
   when unlinking). */
Packit 5c3484
struct header **
Packit 5c3484
tests_memory_find (void *ptr)
Packit 5c3484
{
Packit 5c3484
  struct header  **hp;
Packit 5c3484
Packit 5c3484
  for (hp = &tests_memory_list; *hp != NULL; hp = &((*hp)->next))
Packit 5c3484
    if ((*hp)->ptr == ptr)
Packit 5c3484
      return hp;
Packit 5c3484
Packit 5c3484
  return NULL;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
int
Packit 5c3484
tests_memory_valid (void *ptr)
Packit 5c3484
{
Packit 5c3484
  return (tests_memory_find (ptr) != NULL);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void *
Packit 5c3484
tests_allocate (size_t size)
Packit 5c3484
{
Packit 5c3484
  struct header  *h;
Packit 5c3484
  void *rptr, *ptr;
Packit 5c3484
  mp_limb_t PATTERN2_var;
Packit 5c3484
Packit 5c3484
  if (size == 0)
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "tests_allocate(): attempt to allocate 0 bytes\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  h = (struct header *) __gmp_default_allocate (sizeof (*h));
Packit 5c3484
  h->next = tests_memory_list;
Packit 5c3484
  tests_memory_list = h;
Packit 5c3484
Packit 5c3484
  rptr = __gmp_default_allocate (size + 2 * sizeof (mp_limb_t));
Packit 5c3484
  ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t));
Packit 5c3484
Packit 5c3484
  *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
Packit 5c3484
    = PATTERN1 - PTRLIMB (ptr);
Packit 5c3484
  PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
Packit 5c3484
  memcpy ((void *) ((gmp_intptr_t) ptr + size), &PATTERN2_var, sizeof (mp_limb_t));
Packit 5c3484
Packit 5c3484
  h->size = size;
Packit 5c3484
  h->ptr = ptr;
Packit 5c3484
  return h->ptr;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void *
Packit 5c3484
tests_reallocate (void *ptr, size_t old_size, size_t new_size)
Packit 5c3484
{
Packit 5c3484
  struct header  **hp, *h;
Packit 5c3484
  void *rptr;
Packit 5c3484
  mp_limb_t PATTERN2_var;
Packit 5c3484
Packit 5c3484
  if (new_size == 0)
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "tests_reallocate(): attempt to reallocate %p to 0 bytes\n",
Packit 5c3484
	       ptr);
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  hp = tests_memory_find (ptr);
Packit 5c3484
  if (hp == NULL)
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "tests_reallocate(): attempt to reallocate bad pointer %p\n",
Packit 5c3484
	       ptr);
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
  h = *hp;
Packit 5c3484
Packit 5c3484
  if (h->size != old_size)
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "tests_reallocate(): bad old size %lu, should be %lu\n",
Packit 5c3484
	       (unsigned long) old_size, (unsigned long) h->size);
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
Packit 5c3484
      != PATTERN1 - PTRLIMB (ptr))
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "in realloc: redzone clobbered before block\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
  PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
Packit 5c3484
  if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t)))
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "in realloc: redzone clobbered after block\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  rptr = __gmp_default_reallocate ((void *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)),
Packit 5c3484
				 old_size + 2 * sizeof (mp_limb_t),
Packit 5c3484
				 new_size + 2 * sizeof (mp_limb_t));
Packit 5c3484
  ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t));
Packit 5c3484
Packit 5c3484
  *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
Packit 5c3484
    = PATTERN1 - PTRLIMB (ptr);
Packit 5c3484
  PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
Packit 5c3484
  memcpy ((void *) ((gmp_intptr_t) ptr + new_size), &PATTERN2_var, sizeof (mp_limb_t));
Packit 5c3484
Packit 5c3484
  h->size = new_size;
Packit 5c3484
  h->ptr = ptr;
Packit 5c3484
  return h->ptr;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
struct header **
Packit 5c3484
tests_free_find (void *ptr)
Packit 5c3484
{
Packit 5c3484
  struct header  **hp = tests_memory_find (ptr);
Packit 5c3484
  if (hp == NULL)
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "tests_free(): attempt to free bad pointer %p\n",
Packit 5c3484
	       ptr);
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
  return hp;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
tests_free_nosize (void *ptr)
Packit 5c3484
{
Packit 5c3484
  struct header  **hp = tests_free_find (ptr);
Packit 5c3484
  struct header  *h = *hp;
Packit 5c3484
  mp_limb_t PATTERN2_var;
Packit 5c3484
Packit 5c3484
  *hp = h->next;  /* unlink */
Packit 5c3484
Packit 5c3484
  if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
Packit 5c3484
      != PATTERN1 - PTRLIMB (ptr))
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "in free: redzone clobbered before block\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
  PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
Packit 5c3484
  if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t)))
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "in free: redzone clobbered after block\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  __gmp_default_free ((void *) ((gmp_intptr_t) ptr - sizeof(mp_limb_t)),
Packit 5c3484
		      h->size + 2 * sizeof (mp_limb_t));
Packit 5c3484
  __gmp_default_free (h, sizeof (*h));
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
tests_free (void *ptr, size_t size)
Packit 5c3484
{
Packit 5c3484
  struct header  **hp = tests_free_find (ptr);
Packit 5c3484
  struct header  *h = *hp;
Packit 5c3484
Packit 5c3484
  if (h->size != size)
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "tests_free(): bad size %lu, should be %lu\n",
Packit 5c3484
	       (unsigned long) size, (unsigned long) h->size);
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  tests_free_nosize (ptr);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
tests_memory_start (void)
Packit 5c3484
{
Packit 5c3484
  mp_set_memory_functions (tests_allocate, tests_reallocate, tests_free);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
tests_memory_end (void)
Packit 5c3484
{
Packit 5c3484
  if (tests_memory_list != NULL)
Packit 5c3484
    {
Packit 5c3484
      struct header  *h;
Packit 5c3484
      unsigned  count;
Packit 5c3484
Packit 5c3484
      fprintf (stderr, "tests_memory_end(): not all memory freed\n");
Packit 5c3484
Packit 5c3484
      count = 0;
Packit 5c3484
      for (h = tests_memory_list; h != NULL; h = h->next)
Packit 5c3484
	count++;
Packit 5c3484
Packit 5c3484
      fprintf (stderr, "    %u blocks remaining\n", count);
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
}