1 /* 2 * Unit test suite for memory functions 3 * 4 * Copyright 2003 Dimitrie O. Paun 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdlib.h> 22 #include <malloc.h> 23 #include <errno.h> 24 #include "wine/test.h" 25 26 #ifdef __REACTOS__ 27 #if defined(__GNUC__) && __GNUC__ >= 7 28 #pragma GCC diagnostic ignored "-Walloc-size-larger-than=9223372036854775807" 29 #endif 30 #endif 31 32 static void (__cdecl *p_aligned_free)(void*) = NULL; 33 static void * (__cdecl *p_aligned_malloc)(size_t,size_t) = NULL; 34 static void * (__cdecl *p_aligned_offset_malloc)(size_t,size_t,size_t) = NULL; 35 static void * (__cdecl *p_aligned_realloc)(void*,size_t,size_t) = NULL; 36 static void * (__cdecl *p_aligned_offset_realloc)(void*,size_t,size_t,size_t) = NULL; 37 38 static void test_aligned_malloc(unsigned int size, unsigned int alignment) 39 { 40 void *mem; 41 42 mem = p_aligned_malloc(size, alignment); 43 44 if ((alignment & (alignment - 1)) == 0) 45 ok(mem != NULL, "_aligned_malloc(%d, %d) failed\n", size, alignment); 46 else 47 ok(mem == NULL, "_aligned_malloc(%d, %d) should have failed\n", size, alignment); 48 49 if (mem) 50 { 51 ok(((DWORD_PTR)mem & (alignment ? alignment - 1 : 0)) == 0, 52 "_aligned_malloc(%d, %d) not aligned: %p\n", size, alignment, mem); 53 if (winetest_debug > 1) 54 { 55 void *saved; 56 saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1)); 57 trace("_aligned_malloc(%3d, %3d) returns %p, saved = %p\n", size, alignment, mem, saved ); 58 } 59 p_aligned_free(mem); 60 } 61 else 62 ok(errno == EINVAL, "_aligned_malloc(%d, %d) errno: %d != %d\n", size, alignment, errno, EINVAL); 63 } 64 65 static void test_aligned_offset_malloc(unsigned int size, unsigned int alignment, unsigned int offset) 66 { 67 void *mem; 68 69 mem = p_aligned_offset_malloc(size, alignment, offset); 70 71 if ((alignment & (alignment - 1)) == 0) 72 if (offset < size) 73 ok(mem != NULL, "_aligned_offset_malloc(%d, %d, %d) failed\n", size, alignment, offset); 74 else 75 ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d, %d) errno: %d != %d\n", size, alignment, offset, errno, EINVAL); 76 else 77 ok(mem == NULL, "_aligned_offset_malloc(%d, %d, %d) should have failed\n", size, alignment, offset); 78 79 if (mem) 80 { 81 ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0, 82 "_aligned_offset_malloc(%d, %d, %d) not aligned: %p\n", size, alignment, offset, mem); 83 if (winetest_debug > 1) 84 { 85 void *saved; 86 saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1)); 87 trace("_aligned_offset_malloc(%3d, %3d, %3d) returns %p, saved = %p\n", 88 size, alignment, offset, mem, saved); 89 } 90 p_aligned_free(mem); 91 } 92 else 93 ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d, %d) errno: %d != %d\n", size, alignment, offset, errno, EINVAL); 94 } 95 96 static void test_aligned_realloc(unsigned int size1, unsigned int size2, unsigned int alignment) 97 { 98 void *mem, *mem1, *mem2; 99 100 mem = p_aligned_malloc(size1, alignment); 101 102 if ((alignment & (alignment - 1)) == 0) 103 ok(mem != NULL, "_aligned_malloc(%d, %d) failed\n", size1, alignment); 104 else 105 ok(mem == NULL, "_aligned_malloc(%d, %d) should have failed\n", size1, alignment); 106 107 if (mem) 108 { 109 mem1 = malloc(size1); 110 if (mem1) 111 { 112 unsigned int i; 113 for (i = 0; i < size1; i++) 114 ((char *)mem)[i] = i + 1; 115 memcpy(mem1, mem, size1); 116 } 117 118 ok(((DWORD_PTR)mem & (alignment ? alignment - 1 : 0)) == 0, 119 "_aligned_malloc(%d, %d) not aligned: %p\n", size1, alignment, mem); 120 if (winetest_debug > 1) 121 { 122 void *saved; 123 saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1)); 124 trace("_aligned_malloc(%3d, %3d) returns %p, saved = %p\n", size1, alignment, mem, saved); 125 } 126 127 mem2 = p_aligned_realloc(mem, size2, alignment); 128 129 ok(mem2 != NULL, "_aligned_realloc(%p, %d, %d) failed\n", mem, size2, alignment); 130 131 if (mem2) 132 { 133 ok(((DWORD_PTR)mem2 & (alignment ? alignment - 1 : 0)) == 0, 134 "_aligned_realloc(%p, %d, %d) not aligned: %p\n", mem, size2, alignment, mem2); 135 if (winetest_debug > 1) 136 { 137 void *saved; 138 saved = *(void **)((DWORD_PTR)((char *)mem2 - sizeof(void *)) & ~(sizeof(void *) - 1)); 139 trace("_aligned_realloc(%p, %3d, %3d) returns %p, saved = %p\n", 140 mem, size2, alignment, mem2, saved); 141 } 142 if (mem1) 143 { 144 ok(memcmp(mem2, mem1, min(size1, size2))==0, "_aligned_realloc(%p, %d, %d) has different data\n", mem, size2, alignment); 145 if (memcmp(mem2, mem1, min(size1, size2)) && winetest_debug > 1) 146 { 147 unsigned int i; 148 for (i = 0; i < min(size1, size2); i++) 149 { 150 if (((char *)mem2)[i] != ((char *)mem1)[i]) 151 trace("%d: %02x != %02x\n", i, ((char *)mem2)[i] & 0xff, ((char *)mem1)[i] & 0xff); 152 } 153 } 154 } 155 p_aligned_free(mem2); 156 } else { 157 ok(errno == EINVAL, "_aligned_realloc(%p, %d, %d) errno: %d != %d\n", mem, size2, alignment, errno, EINVAL); 158 p_aligned_free(mem); 159 } 160 161 free(mem1); 162 } 163 else 164 ok(errno == EINVAL, "_aligned_malloc(%d, %d) errno: %d != %d\n", size1, alignment, errno, EINVAL); 165 } 166 167 static void test_aligned_offset_realloc(unsigned int size1, unsigned int size2, 168 unsigned int alignment, unsigned int offset) 169 { 170 void *mem, *mem1, *mem2; 171 172 mem = p_aligned_offset_malloc(size1, alignment, offset); 173 174 if ((alignment & (alignment - 1)) == 0) 175 ok(mem != NULL, "_aligned_offset_malloc(%d, %d, %d) failed\n", size1, alignment, offset); 176 else 177 ok(mem == NULL, "_aligned_offset_malloc(%d, %d, %d) should have failed\n", size1, alignment, offset); 178 179 if (mem) 180 { 181 mem1 = malloc(size1); 182 if (mem1) 183 { 184 unsigned int i; 185 for (i = 0; i < size1; i++) 186 ((char *)mem)[i] = i + 1; 187 memcpy(mem1, mem, size1); 188 } 189 190 ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0, 191 "_aligned_offset_malloc(%d, %d, %d) not aligned: %p\n", size1, alignment, offset, mem); 192 if (winetest_debug > 1) 193 { 194 void *saved; 195 saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1)); 196 trace("_aligned_offset_malloc(%3d, %3d, %3d) returns %p, saved = %p\n", 197 size1, alignment, offset, mem, saved); 198 } 199 200 mem2 = p_aligned_offset_realloc(mem, size2, alignment, offset); 201 202 ok(mem2 != NULL, "_aligned_offset_realloc(%p, %d, %d, %d) failed\n", mem, size2, alignment, offset); 203 204 if (mem2) 205 { 206 ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0, 207 "_aligned_offset_realloc(%p, %d, %d, %d) not aligned: %p\n", mem, size2, alignment, offset, mem2); 208 if (winetest_debug > 1) 209 { 210 void *saved; 211 saved = *(void **)((DWORD_PTR)((char *)mem2 - sizeof(void *)) & ~(sizeof(void *) - 1)); 212 trace("_aligned_offset_realloc(%p, %3d, %3d, %3d) returns %p, saved = %p\n", 213 mem, size2, alignment, offset, mem2, saved); 214 } 215 if (mem1) 216 { 217 ok(memcmp(mem2, mem1, min(size1, size2))==0, "_aligned_offset_realloc(%p, %d, %d, %d) has different data\n", mem, size2, alignment, offset); 218 if (memcmp(mem2, mem1, min(size1, size2)) && winetest_debug > 1) 219 { 220 unsigned int i; 221 for (i = 0; i < min(size1, size2); i++) 222 { 223 if (((char *)mem2)[i] != ((char *)mem1)[i]) 224 trace("%d: %02x != %02x\n", i, ((char *)mem2)[i] & 0xff, ((char *)mem1)[i] & 0xff); 225 } 226 } 227 } 228 p_aligned_free(mem2); 229 } else { 230 ok(errno == EINVAL, "_aligned_offset_realloc(%p, %d, %d, %d) errno: %d != %d\n", mem, size2, alignment, offset, errno, EINVAL); 231 p_aligned_free(mem); 232 } 233 234 free(mem1); 235 } 236 else 237 ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d) errno: %d != %d\n", size1, alignment, errno, EINVAL); 238 } 239 240 static void test_aligned(void) 241 { 242 HMODULE msvcrt = GetModuleHandleA("msvcrt.dll"); 243 244 if (msvcrt == NULL) 245 return; 246 247 p_aligned_free = (void*)GetProcAddress(msvcrt, "_aligned_free"); 248 p_aligned_malloc = (void*)GetProcAddress(msvcrt, "_aligned_malloc"); 249 p_aligned_offset_malloc = (void*)GetProcAddress(msvcrt, "_aligned_offset_malloc"); 250 p_aligned_realloc = (void*)GetProcAddress(msvcrt, "_aligned_realloc"); 251 p_aligned_offset_realloc = (void*)GetProcAddress(msvcrt, "_aligned_offset_realloc"); 252 253 if (!p_aligned_free || !p_aligned_malloc || !p_aligned_offset_malloc || !p_aligned_realloc || !p_aligned_offset_realloc) 254 { 255 skip("aligned memory tests skipped\n"); 256 return; 257 } 258 259 test_aligned_malloc(256, 0); 260 test_aligned_malloc(256, 1); 261 test_aligned_malloc(256, 2); 262 test_aligned_malloc(256, 3); 263 test_aligned_malloc(256, 4); 264 test_aligned_malloc(256, 8); 265 test_aligned_malloc(256, 16); 266 test_aligned_malloc(256, 32); 267 test_aligned_malloc(256, 64); 268 test_aligned_malloc(256, 127); 269 test_aligned_malloc(256, 128); 270 271 test_aligned_offset_malloc(256, 0, 0); 272 test_aligned_offset_malloc(256, 1, 0); 273 test_aligned_offset_malloc(256, 2, 0); 274 test_aligned_offset_malloc(256, 3, 0); 275 test_aligned_offset_malloc(256, 4, 0); 276 test_aligned_offset_malloc(256, 8, 0); 277 test_aligned_offset_malloc(256, 16, 0); 278 test_aligned_offset_malloc(256, 32, 0); 279 test_aligned_offset_malloc(256, 64, 0); 280 test_aligned_offset_malloc(256, 127, 0); 281 test_aligned_offset_malloc(256, 128, 0); 282 283 test_aligned_offset_malloc(256, 0, 4); 284 test_aligned_offset_malloc(256, 1, 4); 285 test_aligned_offset_malloc(256, 2, 4); 286 test_aligned_offset_malloc(256, 3, 4); 287 test_aligned_offset_malloc(256, 4, 4); 288 test_aligned_offset_malloc(256, 8, 4); 289 test_aligned_offset_malloc(256, 16, 4); 290 test_aligned_offset_malloc(256, 32, 4); 291 test_aligned_offset_malloc(256, 64, 4); 292 test_aligned_offset_malloc(256, 127, 4); 293 test_aligned_offset_malloc(256, 128, 4); 294 295 test_aligned_offset_malloc(256, 8, 7); 296 test_aligned_offset_malloc(256, 8, 9); 297 test_aligned_offset_malloc(256, 8, 16); 298 test_aligned_offset_malloc(256, 8, 17); 299 test_aligned_offset_malloc(256, 8, 254); 300 test_aligned_offset_malloc(256, 8, 255); 301 test_aligned_offset_malloc(256, 8, 256); 302 test_aligned_offset_malloc(256, 8, 512); 303 304 test_aligned_realloc(256, 512, 0); 305 test_aligned_realloc(256, 128, 0); 306 test_aligned_realloc(256, 512, 4); 307 test_aligned_realloc(256, 128, 4); 308 test_aligned_realloc(256, 512, 8); 309 test_aligned_realloc(256, 128, 8); 310 test_aligned_realloc(256, 512, 16); 311 test_aligned_realloc(256, 128, 16); 312 test_aligned_realloc(256, 512, 32); 313 test_aligned_realloc(256, 128, 32); 314 test_aligned_realloc(256, 512, 64); 315 test_aligned_realloc(256, 128, 64); 316 317 test_aligned_offset_realloc(256, 512, 0, 0); 318 test_aligned_offset_realloc(256, 128, 0, 0); 319 test_aligned_offset_realloc(256, 512, 4, 0); 320 test_aligned_offset_realloc(256, 128, 4, 0); 321 test_aligned_offset_realloc(256, 512, 8, 0); 322 test_aligned_offset_realloc(256, 128, 8, 0); 323 test_aligned_offset_realloc(256, 512, 16, 0); 324 test_aligned_offset_realloc(256, 128, 16, 0); 325 test_aligned_offset_realloc(256, 512, 32, 0); 326 test_aligned_offset_realloc(256, 128, 32, 0); 327 test_aligned_offset_realloc(256, 512, 64, 0); 328 test_aligned_offset_realloc(256, 128, 64, 0); 329 330 test_aligned_offset_realloc(256, 512, 0, 4); 331 test_aligned_offset_realloc(256, 128, 0, 4); 332 test_aligned_offset_realloc(256, 512, 4, 4); 333 test_aligned_offset_realloc(256, 128, 4, 4); 334 test_aligned_offset_realloc(256, 512, 8, 4); 335 test_aligned_offset_realloc(256, 128, 8, 4); 336 test_aligned_offset_realloc(256, 512, 16, 4); 337 test_aligned_offset_realloc(256, 128, 16, 4); 338 test_aligned_offset_realloc(256, 512, 32, 4); 339 test_aligned_offset_realloc(256, 128, 32, 4); 340 test_aligned_offset_realloc(256, 512, 64, 4); 341 test_aligned_offset_realloc(256, 128, 64, 4); 342 343 test_aligned_offset_realloc(256, 512, 0, 8); 344 test_aligned_offset_realloc(256, 128, 0, 8); 345 test_aligned_offset_realloc(256, 512, 4, 8); 346 test_aligned_offset_realloc(256, 128, 4, 8); 347 test_aligned_offset_realloc(256, 512, 8, 8); 348 test_aligned_offset_realloc(256, 128, 8, 8); 349 test_aligned_offset_realloc(256, 512, 16, 8); 350 test_aligned_offset_realloc(256, 128, 16, 8); 351 test_aligned_offset_realloc(256, 512, 32, 8); 352 test_aligned_offset_realloc(256, 128, 32, 8); 353 test_aligned_offset_realloc(256, 512, 64, 8); 354 test_aligned_offset_realloc(256, 128, 64, 8); 355 356 test_aligned_offset_realloc(256, 512, 0, 16); 357 test_aligned_offset_realloc(256, 128, 0, 16); 358 test_aligned_offset_realloc(256, 512, 4, 16); 359 test_aligned_offset_realloc(256, 128, 4, 16); 360 test_aligned_offset_realloc(256, 512, 8, 16); 361 test_aligned_offset_realloc(256, 128, 8, 16); 362 test_aligned_offset_realloc(256, 512, 16, 16); 363 test_aligned_offset_realloc(256, 128, 16, 16); 364 test_aligned_offset_realloc(256, 512, 32, 16); 365 test_aligned_offset_realloc(256, 128, 32, 16); 366 test_aligned_offset_realloc(256, 512, 64, 16); 367 test_aligned_offset_realloc(256, 128, 64, 16); 368 369 test_aligned_offset_realloc(256, 512, 0, 32); 370 test_aligned_offset_realloc(256, 128, 0, 32); 371 test_aligned_offset_realloc(256, 512, 4, 32); 372 test_aligned_offset_realloc(256, 128, 4, 32); 373 test_aligned_offset_realloc(256, 512, 8, 32); 374 test_aligned_offset_realloc(256, 128, 8, 32); 375 test_aligned_offset_realloc(256, 512, 16, 32); 376 test_aligned_offset_realloc(256, 128, 16, 32); 377 test_aligned_offset_realloc(256, 512, 32, 32); 378 test_aligned_offset_realloc(256, 128, 32, 32); 379 test_aligned_offset_realloc(256, 512, 64, 32); 380 test_aligned_offset_realloc(256, 128, 64, 32); 381 382 test_aligned_offset_realloc(256, 512, 0, 64); 383 test_aligned_offset_realloc(256, 128, 0, 64); 384 test_aligned_offset_realloc(256, 512, 4, 64); 385 test_aligned_offset_realloc(256, 128, 4, 64); 386 test_aligned_offset_realloc(256, 512, 8, 64); 387 test_aligned_offset_realloc(256, 128, 8, 64); 388 test_aligned_offset_realloc(256, 512, 16, 64); 389 test_aligned_offset_realloc(256, 128, 16, 64); 390 test_aligned_offset_realloc(256, 512, 32, 64); 391 test_aligned_offset_realloc(256, 128, 32, 64); 392 test_aligned_offset_realloc(256, 512, 64, 64); 393 test_aligned_offset_realloc(256, 128, 64, 64); 394 395 test_aligned_offset_realloc(256, 512, 0, 96); 396 test_aligned_offset_realloc(256, 128, 0, 96); 397 test_aligned_offset_realloc(256, 512, 4, 96); 398 test_aligned_offset_realloc(256, 128, 4, 96); 399 test_aligned_offset_realloc(256, 512, 8, 96); 400 test_aligned_offset_realloc(256, 128, 8, 96); 401 test_aligned_offset_realloc(256, 512, 16, 96); 402 test_aligned_offset_realloc(256, 128, 16, 96); 403 test_aligned_offset_realloc(256, 512, 32, 96); 404 test_aligned_offset_realloc(256, 128, 32, 96); 405 test_aligned_offset_realloc(256, 512, 64, 96); 406 test_aligned_offset_realloc(256, 128, 64, 96); 407 408 test_aligned_offset_realloc(256, 512, 0, 112); 409 test_aligned_offset_realloc(256, 128, 0, 112); 410 test_aligned_offset_realloc(256, 512, 4, 112); 411 test_aligned_offset_realloc(256, 128, 4, 112); 412 test_aligned_offset_realloc(256, 512, 8, 112); 413 test_aligned_offset_realloc(256, 128, 8, 112); 414 test_aligned_offset_realloc(256, 512, 16, 112); 415 test_aligned_offset_realloc(256, 128, 16, 112); 416 test_aligned_offset_realloc(256, 512, 32, 112); 417 test_aligned_offset_realloc(256, 128, 32, 112); 418 test_aligned_offset_realloc(256, 512, 64, 112); 419 test_aligned_offset_realloc(256, 128, 64, 112); 420 } 421 422 static void test_sbheap(void) 423 { 424 void *mem; 425 int threshold; 426 427 if(sizeof(void*) == 8) { 428 ok(!_set_sbh_threshold(0), "_set_sbh_threshold succeeded\n"); 429 ok(!_set_sbh_threshold(1000), "_set_sbh_threshold succeeded\n"); 430 return; 431 } 432 433 mem = malloc(1); 434 ok(mem != NULL, "malloc failed\n"); 435 436 ok(_set_sbh_threshold(1), "_set_sbh_threshold failed\n"); 437 threshold = _get_sbh_threshold(); 438 ok(threshold == 16, "threshold = %d\n", threshold); 439 440 ok(_set_sbh_threshold(8), "_set_sbh_threshold failed\n"); 441 threshold = _get_sbh_threshold(); 442 ok(threshold == 16, "threshold = %d\n", threshold); 443 444 ok(_set_sbh_threshold(1000), "_set_sbh_threshold failed\n"); 445 threshold = _get_sbh_threshold(); 446 ok(threshold == 1008, "threshold = %d\n", threshold); 447 448 free(mem); 449 450 mem = malloc(1); 451 ok(mem != NULL, "malloc failed\n"); 452 ok(!((UINT_PTR)mem & 0xf), "incorrect alignment (%p)\n", mem); 453 454 mem = realloc(mem, 10); 455 ok(mem != NULL, "realloc failed\n"); 456 ok(!((UINT_PTR)mem & 0xf), "incorrect alignment (%p)\n", mem); 457 458 ok(_set_sbh_threshold(0), "_set_sbh_threshold failed\n"); 459 threshold = _get_sbh_threshold(); 460 ok(threshold == 0, "threshold = %d\n", threshold); 461 462 free(mem); 463 } 464 465 static void test_calloc(void) 466 { 467 /* use function pointer to bypass gcc builtin */ 468 void *(__cdecl *p_calloc)(size_t, size_t); 469 void *ptr; 470 471 p_calloc = (void *)GetProcAddress( GetModuleHandleA("msvcrt.dll"), "calloc"); 472 473 ptr = p_calloc(1, 0); 474 ok(ptr != NULL, "got %p\n", ptr); 475 free(ptr); 476 477 ptr = p_calloc(0, 0); 478 ok(ptr != NULL, "got %p\n", ptr); 479 free(ptr); 480 481 ptr = p_calloc(0, 1); 482 ok(ptr != NULL, "got %p\n", ptr); 483 free(ptr); 484 485 errno = 0; 486 ptr = p_calloc(~(size_t)0 / 2, ~(size_t)0 / 2); 487 ok(ptr == NULL || broken(ptr != NULL) /* winxp sp0 */, "got %p\n", ptr); 488 ok(errno == ENOMEM || broken(errno == 0) /* winxp, win2k3 */, "got errno %d\n", errno); 489 free(ptr); 490 } 491 492 START_TEST(heap) 493 { 494 void *mem; 495 496 mem = malloc(0); 497 ok(mem != NULL, "memory not allocated for size 0\n"); 498 free(mem); 499 500 mem = realloc(NULL, 10); 501 ok(mem != NULL, "memory not allocated\n"); 502 503 mem = realloc(mem, 20); 504 ok(mem != NULL, "memory not reallocated\n"); 505 506 mem = realloc(mem, 0); 507 ok(mem == NULL, "memory not freed\n"); 508 509 mem = realloc(NULL, 0); 510 ok(mem != NULL, "memory not (re)allocated for size 0\n"); 511 512 free(mem); 513 514 test_aligned(); 515 test_sbheap(); 516 test_calloc(); 517 } 518