1 /* 2 3 Copyright 2013-2015, 2018 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 "testutils.h" 21 22 /* Include it here, so we we could tweak, e.g., how MPZ_REALLOC 23 works. */ 24 #include "../mini-gmp.c" 25 #include "../mini-mpq.c" 26 27 static size_t total_alloc = 0; 28 29 /* Custom memory allocation to track memory usage, and add a small red 30 zone. 31 32 About alignment: In general, getting a block from malloc, and 33 incrementing it by sizeof(size_t), like we do here, might give a 34 pointer which is not properly aligned for all types. But the 35 largest type we allocate space for is unsigned long (mp_limb_t), 36 which shouldn't have stricter alignment requirements than 37 size_t. */ 38 39 static unsigned char block_end[8] = 40 { 0x7c, 0x37, 0xd6, 0x12, 0xa8, 0x6c, 0x01, 0xd1 }; 41 42 static void * 43 block_init (size_t *block, size_t size) 44 { 45 char *p; 46 *block++ = size; 47 48 p = (char *) block; 49 memcpy (p + size, block_end, sizeof(block_end)); 50 51 total_alloc += size; 52 return p; 53 } 54 55 /* Check small redzone, return pointer to malloced block. */ 56 static size_t * 57 block_check (void *p) 58 { 59 size_t *block = (size_t *) p - 1; 60 size_t size = block[0]; 61 62 if (memcmp ((char *)p + size, block_end, sizeof(block_end)) != 0) 63 { 64 fprintf (stderr, "red zone overwritten.\n"); 65 abort (); 66 } 67 total_alloc -= size; 68 return block; 69 } 70 71 static void * 72 tu_alloc (size_t size) 73 { 74 size_t *block = (size_t *) malloc (sizeof(size_t) + size + sizeof(block_end)); 75 if (!block) 76 { 77 fprintf (stderr, "Virtual memory exhausted.\n"); 78 abort (); 79 } 80 81 return block_init (block, size); 82 } 83 84 static void * 85 tu_realloc (void *p, size_t old_size, size_t new_size) 86 { 87 size_t *block = block_check (p); 88 block = (size_t *) realloc (block, sizeof(size_t) + new_size + sizeof(block_end)); 89 if (!block) 90 { 91 fprintf (stderr, "Virtual memory exhausted.\n"); 92 abort (); 93 } 94 95 return block_init (block, new_size); 96 } 97 98 static void 99 tu_free (void *p, size_t old_size) 100 { 101 free (block_check (p)); 102 } 103 104 /* Free memory allocated via mini-gmp allocation function. */ 105 void 106 testfree (void *p) 107 { 108 void (*freefunc) (void *, size_t); 109 mp_get_memory_functions (NULL, NULL, &freefunc); 110 111 freefunc (p, 0); 112 } 113 114 int 115 main (int argc, char **argv) 116 { 117 hex_random_init (); 118 119 mp_set_memory_functions (tu_alloc, tu_realloc, tu_free); 120 121 /* Currently, t-comb seems to be the only program accepting any 122 arguments. It might make sense to parse common arguments here. */ 123 testmain (argc, argv); 124 125 if (total_alloc != 0) 126 { 127 fprintf (stderr, "Memory leaked: %lu bytes.\n", 128 (unsigned long) total_alloc); 129 abort (); 130 } 131 return 0; 132 } 133 134 void 135 testhalves (int count, void (*tested_fun) (int)) 136 { 137 void (*freefunc) (void *, size_t); 138 void *(*reallocfunc) (void *, size_t, size_t); 139 void *(*allocfunc) (size_t); 140 size_t initial_alloc; 141 142 mp_get_memory_functions (&allocfunc, &reallocfunc, &freefunc); 143 initial_alloc = total_alloc; 144 (*tested_fun) (count / 2); 145 if (initial_alloc != total_alloc) 146 { 147 fprintf (stderr, "First half, memory leaked: %lu bytes.\n", 148 (unsigned long) total_alloc - initial_alloc); 149 abort (); 150 } 151 mp_set_memory_functions (NULL, NULL, NULL); 152 (*tested_fun) (count / 2); 153 mp_set_memory_functions (allocfunc, reallocfunc, freefunc); 154 } 155 156 void 157 dump (const char *label, const mpz_t x) 158 { 159 char *buf = mpz_get_str (NULL, 16, x); 160 fprintf (stderr, "%s: %s\n", label, buf); 161 testfree (buf); 162 } 163 164 void 165 mpz_set_str_or_abort (mpz_ptr z, const char *str, int base) 166 { 167 if (mpz_set_str (z, str, base) != 0) 168 { 169 fprintf (stderr, "ERROR: mpz_set_str failed\n"); 170 fprintf (stderr, " str = \"%s\"\n", str); 171 fprintf (stderr, " base = %d\n", base); 172 abort(); 173 } 174 } 175 176 int 177 mpz_lucas_mod (mpz_t V, mpz_t Qk, long Q, 178 mp_bitcnt_t b0, const mpz_t n) 179 { 180 return gmp_lucas_mod (V, Qk, Q, b0, n); 181 } 182