(root)/
gmp-6.3.0/
tests/
memory.c
       1  /* Memory allocation used during tests.
       2  
       3  Copyright 2001, 2002, 2007, 2013 Free Software Foundation, Inc.
       4  
       5  This file is part of the GNU MP Library test suite.
       6  
       7  The GNU MP Library test suite is free software; you can redistribute it
       8  and/or modify it under the terms of the GNU General Public License as
       9  published by the Free Software Foundation; either version 3 of the License,
      10  or (at your option) any later version.
      11  
      12  The GNU MP Library test suite is distributed in the hope that it will be
      13  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
      15  Public License for more details.
      16  
      17  You should have received a copy of the GNU General Public License along with
      18  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
      19  
      20  #include <stdio.h>
      21  #include <stdlib.h>		/* for abort */
      22  #include <string.h>		/* for memcpy, memcmp */
      23  #include "gmp-impl.h"
      24  #include "tests.h"
      25  
      26  #if GMP_LIMB_BITS == 64
      27  #define PATTERN1 CNST_LIMB(0xcafebabedeadbeef)
      28  #define PATTERN2 CNST_LIMB(0xabacadabaedeedab)
      29  #else
      30  #define PATTERN1 CNST_LIMB(0xcafebabe)
      31  #define PATTERN2 CNST_LIMB(0xdeadbeef)
      32  #endif
      33  
      34  #if HAVE_INTPTR_T
      35  #define PTRLIMB(p)  ((mp_limb_t) (intptr_t) p)
      36  #else
      37  #define PTRLIMB(p)  ((mp_limb_t) (size_t) p)
      38  #endif
      39  
      40  /* Each block allocated is a separate malloc, for the benefit of a redzoning
      41     malloc debugger during development or when bug hunting.
      42  
      43     Sizes passed when reallocating or freeing are checked (the default
      44     routines don't care about these).
      45  
      46     Memory leaks are checked by requiring that all blocks have been freed
      47     when tests_memory_end() is called.  Test programs must be sure to have
      48     "clear"s for all temporary variables used.  */
      49  
      50  
      51  struct header {
      52    void           *ptr;
      53    size_t         size;
      54    struct header  *next;
      55  };
      56  
      57  struct header  *tests_memory_list = NULL;
      58  
      59  /* Return a pointer to a pointer to the found block (so it can be updated
      60     when unlinking). */
      61  struct header **
      62  tests_memory_find (void *ptr)
      63  {
      64    struct header  **hp;
      65  
      66    for (hp = &tests_memory_list; *hp != NULL; hp = &((*hp)->next))
      67      if ((*hp)->ptr == ptr)
      68        return hp;
      69  
      70    return NULL;
      71  }
      72  
      73  int
      74  tests_memory_valid (void *ptr)
      75  {
      76    return (tests_memory_find (ptr) != NULL);
      77  }
      78  
      79  void *
      80  tests_allocate (size_t size)
      81  {
      82    struct header  *h;
      83    void *rptr, *ptr;
      84    mp_limb_t PATTERN2_var;
      85  
      86    if (size == 0)
      87      {
      88        fprintf (stderr, "tests_allocate(): attempt to allocate 0 bytes\n");
      89        abort ();
      90      }
      91  
      92    h = (struct header *) __gmp_default_allocate (sizeof (*h));
      93    h->next = tests_memory_list;
      94    tests_memory_list = h;
      95  
      96    rptr = __gmp_default_allocate (size + 2 * sizeof (mp_limb_t));
      97    ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t));
      98  
      99    *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
     100      = PATTERN1 - PTRLIMB (ptr);
     101    PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
     102    memcpy ((void *) ((gmp_intptr_t) ptr + size), &PATTERN2_var, sizeof (mp_limb_t));
     103  
     104    h->size = size;
     105    h->ptr = ptr;
     106    return h->ptr;
     107  }
     108  
     109  void *
     110  tests_reallocate (void *ptr, size_t old_size, size_t new_size)
     111  {
     112    struct header  **hp, *h;
     113    void *rptr;
     114    mp_limb_t PATTERN2_var;
     115  
     116    if (new_size == 0)
     117      {
     118        fprintf (stderr, "tests_reallocate(): attempt to reallocate %p to 0 bytes\n",
     119  	       ptr);
     120        abort ();
     121      }
     122  
     123    hp = tests_memory_find (ptr);
     124    if (hp == NULL)
     125      {
     126        fprintf (stderr, "tests_reallocate(): attempt to reallocate bad pointer %p\n",
     127  	       ptr);
     128        abort ();
     129      }
     130    h = *hp;
     131  
     132    if (h->size != old_size)
     133      {
     134        fprintf (stderr, "tests_reallocate(): bad old size %lu, should be %lu\n",
     135  	       (unsigned long) old_size, (unsigned long) h->size);
     136        abort ();
     137      }
     138  
     139    if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
     140        != PATTERN1 - PTRLIMB (ptr))
     141      {
     142        fprintf (stderr, "in realloc: redzone clobbered before block\n");
     143        abort ();
     144      }
     145    PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
     146    if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t)))
     147      {
     148        fprintf (stderr, "in realloc: redzone clobbered after block\n");
     149        abort ();
     150      }
     151  
     152    rptr = __gmp_default_reallocate ((void *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)),
     153  				 old_size + 2 * sizeof (mp_limb_t),
     154  				 new_size + 2 * sizeof (mp_limb_t));
     155    ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t));
     156  
     157    *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
     158      = PATTERN1 - PTRLIMB (ptr);
     159    PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
     160    memcpy ((void *) ((gmp_intptr_t) ptr + new_size), &PATTERN2_var, sizeof (mp_limb_t));
     161  
     162    h->size = new_size;
     163    h->ptr = ptr;
     164    return h->ptr;
     165  }
     166  
     167  struct header **
     168  tests_free_find (void *ptr)
     169  {
     170    struct header  **hp = tests_memory_find (ptr);
     171    if (hp == NULL)
     172      {
     173        fprintf (stderr, "tests_free(): attempt to free bad pointer %p\n",
     174  	       ptr);
     175        abort ();
     176      }
     177    return hp;
     178  }
     179  
     180  void
     181  tests_free_nosize (void *ptr)
     182  {
     183    struct header  **hp = tests_free_find (ptr);
     184    struct header  *h = *hp;
     185    mp_limb_t PATTERN2_var;
     186  
     187    *hp = h->next;  /* unlink */
     188  
     189    if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
     190        != PATTERN1 - PTRLIMB (ptr))
     191      {
     192        fprintf (stderr, "in free: redzone clobbered before block\n");
     193        abort ();
     194      }
     195    PATTERN2_var = PATTERN2 - PTRLIMB (ptr);
     196    if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t)))
     197      {
     198        fprintf (stderr, "in free: redzone clobbered after block\n");
     199        abort ();
     200      }
     201  
     202    __gmp_default_free ((void *) ((gmp_intptr_t) ptr - sizeof(mp_limb_t)),
     203  		      h->size + 2 * sizeof (mp_limb_t));
     204    __gmp_default_free (h, sizeof (*h));
     205  }
     206  
     207  void
     208  tests_free (void *ptr, size_t size)
     209  {
     210    struct header  **hp = tests_free_find (ptr);
     211    struct header  *h = *hp;
     212  
     213    if (h->size != size)
     214      {
     215        fprintf (stderr, "tests_free(): bad size %lu, should be %lu\n",
     216  	       (unsigned long) size, (unsigned long) h->size);
     217        abort ();
     218      }
     219  
     220    tests_free_nosize (ptr);
     221  }
     222  
     223  void
     224  tests_memory_start (void)
     225  {
     226    mp_set_memory_functions (tests_allocate, tests_reallocate, tests_free);
     227  }
     228  
     229  void
     230  tests_memory_end (void)
     231  {
     232    if (tests_memory_list != NULL)
     233      {
     234        struct header  *h;
     235        unsigned  count;
     236  
     237        fprintf (stderr, "tests_memory_end(): not all memory freed\n");
     238  
     239        count = 0;
     240        for (h = tests_memory_list; h != NULL; h = h->next)
     241  	count++;
     242  
     243        fprintf (stderr, "    %u blocks remaining\n", count);
     244        abort ();
     245      }
     246  }