main.cpp revision a63c049f23c49b6345bf2c845a415109c5471ebe
1/* 2** Copyright 2013 The Android Open Source Project 3** 4** Licensed under the Apache License, Version 2.0 (the "License"); 5** you may not use this file except in compliance with the License. 6** You may obtain a copy of the License at 7** 8** http://www.apache.org/licenses/LICENSE-2.0 9** 10** Unless required by applicable law or agreed to in writing, software 11** distributed under the License is distributed on an "AS IS" BASIS, 12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13** See the License for the specific language governing permissions and 14** limitations under the License. 15*/ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <unistd.h> 20#include <sys/mman.h> 21 22// Put any local test functions into the extern below. 23extern "C" { 24} 25 26#define FENCEPOST_LENGTH 8 27 28#define MAX_MEMCPY_TEST_SIZE 2048 29#define MAX_MEMCPY_BUFFER_SIZE (3 * MAX_MEMCPY_TEST_SIZE) 30 31#define MAX_MEMSET_TEST_SIZE 2048 32#define MAX_MEMSET_BUFFER_SIZE (3 * MAX_MEMSET_TEST_SIZE) 33 34#define MAX_STRCMP_TEST_SIZE 1024 35#define MAX_STRCMP_BUFFER_SIZE (3 * MAX_STRCMP_TEST_SIZE) 36 37#define MAX_STRLEN_TEST_SIZE 1024 38#define MAX_STRLEN_BUFFER_SIZE (3 * MAX_STRLEN_TEST_SIZE) 39 40// Return a pointer into the current string with the specified alignment. 41void *getAlignedPtr(void *orig_ptr, int alignment, int or_mask) { 42 uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr); 43 if (alignment > 0) { 44 // When setting the alignment, set it to exactly the alignment chosen. 45 // The pointer returned will be guaranteed not to be aligned to anything 46 // more than that. 47 ptr += alignment - (ptr & (alignment - 1)); 48 ptr |= alignment | or_mask; 49 } 50 51 return reinterpret_cast<void*>(ptr); 52} 53 54void setFencepost(uint8_t *buffer) { 55 for (int i = 0; i < FENCEPOST_LENGTH; i += 2) { 56 buffer[i] = 0xde; 57 buffer[i+1] = 0xad; 58 } 59} 60 61bool verifyFencepost(uint8_t *buffer) { 62 for (int i = 0; i < FENCEPOST_LENGTH; i += 2) { 63 if (buffer[i] != 0xde || buffer[i+1] != 0xad) { 64 uint8_t expected_value; 65 if (buffer[i] == 0xde) { 66 i++; 67 expected_value = 0xad; 68 } else { 69 expected_value = 0xde; 70 } 71 printf(" mismatch at fencepost[%d], expected %d found %d\n", 72 i, expected_value, buffer[i]); 73 return false; 74 } 75 } 76 return true; 77} 78 79bool doStrcmpExpectEqual(char *string1, char *string2, int align[4], 80 int (*test_strcmp)(const char *s1, const char *s2), 81 bool verbose) { 82 char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]); 83 char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]); 84 85 for (size_t i = 0; i < MAX_STRCMP_TEST_SIZE; i++) { 86 for (size_t j = 0; j < i; j++) { 87 align_str1[j] = (char)(32 + (j % 96)); 88 align_str2[j] = align_str1[j]; 89 } 90 align_str1[i] = '\0'; 91 align_str2[i] = '\0'; 92 93 // Set the characters after the string terminates to different values 94 // to verify that the strcmp is not over checking. 95 for (size_t j = i+1; j < i+64; j++) { 96 align_str1[j] = (char)(32 + j); 97 align_str2[j] = (char)(40 + j); 98 } 99 100 if (verbose) { 101 printf("Testing size %d, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n", 102 i, align_str1, align[0], align[1], align_str2, align[2], align[3]); 103 } 104 105 if (test_strcmp(align_str1, align_str2) != 0) { 106 printf(" Failed at size %d, src1 %p, src2 %p\n", 107 i, align_str1, align_str2); 108 return false; 109 } 110 } 111 112 return true; 113} 114 115bool doStrcmpExpectDiff(char *string1, char *string2, int diff_align[2], 116 int align[4], char diff_char, 117 int (*test_strcmp)(const char *s1, const char *s2), 118 bool verbose) { 119 char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]); 120 char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]); 121 122 for (int i = 0; i < MAX_STRCMP_TEST_SIZE; i++) { 123 // Use valid ascii characters, no unprintables characters. 124 align_str1[i] = (char)(32 + (i % 96)); 125 if (align_str1[i] == diff_char) { 126 // Assumes that one less than the diff character is still a valid 127 // character. 128 align_str1[i] = diff_char-1; 129 } 130 align_str2[i] = align_str1[i]; 131 } 132 align_str1[MAX_STRCMP_TEST_SIZE] = '\0'; 133 align_str2[MAX_STRCMP_TEST_SIZE] = '\0'; 134 135 // Quick check to make sure that the strcmp knows that everything is 136 // equal. If it's so broken that it already thinks the strings are 137 // different, then there is no point running any of the other tests. 138 if (test_strcmp(align_str1, align_str2) != 0) { 139 printf(" strcmp is too broken to do difference testing.\n"); 140 return false; 141 } 142 143 // Get a pointer into the string at the specified alignment. 144 char *bad = (char*)getAlignedPtr(align_str1+MAX_STRCMP_TEST_SIZE/2, 145 diff_align[0], diff_align[1]); 146 147 char saved_char = bad[0]; 148 bad[0] = diff_char; 149 150 if (verbose) { 151 printf("Testing difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n", 152 align_str1, align[0], align[1], align_str2, align[2], align[3]); 153 } 154 if (test_strcmp(align_str1, align_str2) == 0) { 155 printf(" Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n", 156 MAX_STRCMP_TEST_SIZE, align_str1, align_str2, bad); 157 return false; 158 } 159 bad[0] = saved_char; 160 161 // Re-verify that something hasn't gone horribly wrong. 162 if (test_strcmp(align_str1, align_str2) != 0) { 163 printf(" strcmp is too broken to do difference testing.\n"); 164 return false; 165 } 166 167 bad = (char*)getAlignedPtr(align_str2+MAX_STRCMP_TEST_SIZE/2, diff_align[0], 168 diff_align[1]); 169 bad[0] = diff_char; 170 171 if (verbose) { 172 printf("Testing reverse difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n", 173 align_str1, align[0], align[1], align_str2, align[2], align[3]); 174 } 175 if (test_strcmp(align_str1, align_str2) == 0) { 176 printf(" Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n", 177 MAX_STRCMP_TEST_SIZE, align_str1, align_str2, bad); 178 return false; 179 } 180 181 return true; 182} 183 184bool doStrcmpCheckRead(int (*test_strcmp)(const char *s1, const char *s2), 185 bool verbose) { 186 // In order to verify that the strcmp is not reading past the end of the 187 // string, create some strings that end near unreadable memory. 188 long pagesize = sysconf(_SC_PAGE_SIZE); 189 char *memory = (char*)memalign(pagesize, 2 * pagesize); 190 if (memory == NULL) { 191 perror("Unable to allocate memory.\n"); 192 return false; 193 } 194 195 // Make the second page unreadable and unwritable. 196 if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) { 197 perror("Unable to set protection of page.\n"); 198 return false; 199 } 200 201 size_t max_size = pagesize < MAX_STRCMP_TEST_SIZE ? pagesize-1 : MAX_STRCMP_TEST_SIZE; 202 // Allocate an extra byte beyond the string terminator to allow us to 203 // extend the string to be larger than our protected string. 204 char *other_string = (char *)malloc(max_size+2); 205 if (other_string == NULL) { 206 perror("Unable to allocate memory.\n"); 207 return false; 208 } 209 char *string; 210 for (size_t i = 0; i <= max_size; i++) { 211 string = &memory[pagesize-i-1]; 212 for (size_t j = 0; j < i; j++) { 213 other_string[j] = (char)(32 + (j % 96)); 214 string[j] = other_string[j]; 215 } 216 other_string[i] = '\0'; 217 string[i] = '\0'; 218 219 if (verbose) { 220 printf("Testing size %d, strings equal.\n", i); 221 } 222 if (test_strcmp(other_string, string) != 0) { 223 printf(" Failed at size %d, src1 %p, src2 %p\n", i, other_string, string); 224 return false; 225 } 226 227 if (verbose) { 228 printf("Testing size %d, strings equal reverse strings.\n", i); 229 } 230 if (test_strcmp(string, other_string) != 0) { 231 printf(" Failed at size %d, src1 %p, src2 %p\n", i, string, other_string); 232 return false; 233 } 234 235 // Now make other_string longer than our protected string. 236 other_string[i] = '1'; 237 other_string[i+1] = '\0'; 238 239 if (verbose) { 240 printf("Testing size %d, strings not equal.\n", i); 241 } 242 if (test_strcmp(other_string, string) == 0) { 243 printf(" Failed at size %d, src1 %p, src2 %p\n", i, other_string, string); 244 return false; 245 } 246 247 if (verbose) { 248 printf("Testing size %d, strings not equal reverse the strings.\n", i); 249 } 250 if (test_strcmp(string, other_string) == 0) { 251 printf(" Failed at size %d, src1 %p, src2 %p\n", i, string, other_string); 252 return false; 253 } 254 } 255 return true; 256} 257 258bool runStrcmpTest(int (*test_strcmp)(const char *s1, const char *s2), 259 bool verbose) { 260 // Allocate two large buffers to hold the two strings. 261 char *string1 = reinterpret_cast<char*>(malloc(MAX_STRCMP_BUFFER_SIZE+1)); 262 char *string2 = reinterpret_cast<char*>(malloc(MAX_STRCMP_BUFFER_SIZE+1)); 263 if (string1 == NULL || string2 == NULL) { 264 perror("Unable to allocate memory.\n"); 265 return false; 266 } 267 268 // Initialize the strings to be exactly the same. 269 for (int i = 0; i < MAX_STRCMP_BUFFER_SIZE; i++) { 270 string1[i] = (char)(32 + (i % 96)); 271 string2[i] = string1[i]; 272 } 273 string1[MAX_STRCMP_BUFFER_SIZE] = '\0'; 274 string2[MAX_STRCMP_BUFFER_SIZE] = '\0'; 275 276 // Check different string alignments. All zeroes indicates that the 277 // unmodified malloc values should be used. 278 int string_aligns[][4] = { 279 // All zeroes to use the values returned from malloc. 280 { 0, 0, 0, 0 }, 281 282 { 1, 0, 1, 0 }, 283 { 2, 0, 2, 0 }, 284 { 4, 0, 4, 0 }, 285 { 8, 0, 8, 0 }, 286 287 { 8, 0, 4, 0 }, 288 { 4, 0, 8, 0 }, 289 290 { 8, 0, 8, 1 }, 291 { 8, 0, 8, 2 }, 292 { 8, 0, 8, 3 }, 293 { 8, 1, 8, 0 }, 294 { 8, 2, 8, 0 }, 295 { 8, 3, 8, 0 }, 296 297 { 4, 0, 4, 1 }, 298 { 4, 0, 4, 2 }, 299 { 4, 0, 4, 3 }, 300 { 4, 1, 4, 0 }, 301 { 4, 2, 4, 0 }, 302 { 4, 3, 4, 0 }, 303 }; 304 305 printf(" Verifying equal sized strings at different alignments.\n"); 306 for (size_t i = 0; i < sizeof(string_aligns)/sizeof(int[4]); i++) { 307 if (!doStrcmpExpectEqual(string1, string2, string_aligns[i], test_strcmp, 308 verbose)) { 309 return false; 310 } 311 } 312 313 // Test the function finds strings with differences at specific locations. 314 int diff_aligns[][2] = { 315 { 4, 0 }, 316 { 4, 1 }, 317 { 4, 2 }, 318 { 4, 3 }, 319 { 8, 0 }, 320 { 8, 1 }, 321 { 8, 2 }, 322 { 8, 3 }, 323 }; 324 printf(" Verifying different strings at different alignments.\n"); 325 for (size_t i = 0; i < sizeof(diff_aligns)/sizeof(int[2]); i++) { 326 // First loop put the string terminator at the chosen alignment. 327 for (size_t j = 0; j < sizeof(string_aligns)/sizeof(int[4]); j++) { 328 if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i], 329 string_aligns[j], '\0', test_strcmp, verbose)) { 330 return false; 331 } 332 } 333 // Second loop put a different character at the chosen alignment. 334 // This character is guaranteed not to be in the original string. 335 for (size_t j = 0; j < sizeof(string_aligns)/sizeof(int[4]); j++) { 336 if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i], 337 string_aligns[j], '\0', test_strcmp, verbose)) { 338 return false; 339 } 340 } 341 } 342 343 printf(" Verifying strcmp does not read too many bytes.\n"); 344 if (!doStrcmpCheckRead(test_strcmp, verbose)) { 345 return false; 346 } 347 348 printf(" All tests pass.\n"); 349 350 return true; 351} 352 353bool doStrlenCheck(size_t size, char *string, int align, int or_mask, 354 size_t (*test_strlen)(const char *), bool verbose) { 355 char *aligned_string = reinterpret_cast<char*>(getAlignedPtr(string, align, or_mask)); 356 size_t len; 357 if (verbose) { 358 printf("Testing size %d, align=%p[%d,%d]\n", size, aligned_string, align, or_mask); 359 } 360 361 aligned_string[size] = '\0'; 362 len = test_strlen(aligned_string); 363 if (len != size) { 364 printf("Failed at size %d, length returned %u, align=%p[%d,%d]\n", 365 size, len, aligned_string, align, or_mask); 366 return false; 367 } 368 369 if (verbose) { 370 printf("Testing size %d with extra zeros after string, align=%p[%d,%d]\n", 371 size, aligned_string, align, or_mask); 372 } 373 374 for (size_t j = size+1; j <= size+16; j++) { 375 aligned_string[j] = '\0'; 376 } 377 378 len = test_strlen(aligned_string); 379 if (len != size) { 380 printf("Failed at size %d, length returned %u with zeroes after string, align=%p[%d,%d]\n", 381 size, len, aligned_string, align, or_mask); 382 return false; 383 } 384 385 for (size_t j = size; j <= size+16; j++) { 386 aligned_string[j] = (char)(32 + (j % 96)); 387 } 388 return true; 389} 390 391bool runStrlenTest(size_t (*test_strlen)(const char *), 392 bool verbose) { 393 // Allocate two large buffers to hold the two strings. 394 char *string = reinterpret_cast<char*>(malloc(MAX_STRLEN_BUFFER_SIZE+1)); 395 if (string == NULL) { 396 perror("Unable to allocate memory.\n"); 397 return false; 398 } 399 400 // Initialize the strings to be exactly the same. 401 for (int i = 0; i < MAX_STRLEN_BUFFER_SIZE; i++) { 402 string[i] = (char)(32 + (i % 96)); 403 } 404 string[MAX_STRLEN_BUFFER_SIZE] = '\0'; 405 406 // Check different string alignments. All zeroes indicates that the 407 // unmodified malloc values should be used. 408 int aligns[][2] = { 409 // All zeroes to use the values returned from malloc. 410 { 0, 0 }, 411 412 { 1, 0 }, 413 { 2, 0 }, 414 { 4, 0 }, 415 { 8, 0 }, 416 { 16, 0 }, 417 { 32, 0 }, 418 419 { 8, 1 }, 420 { 8, 2 }, 421 { 8, 3 }, 422 423 { 4, 1 }, 424 { 4, 2 }, 425 { 4, 3 }, 426 }; 427 428 printf(" Verifying string lengths at different alignments.\n"); 429 for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) { 430 for (size_t j = 0; j <= MAX_STRLEN_TEST_SIZE; j++) { 431 if (!doStrlenCheck(j, string, aligns[i][0], aligns[i][1], test_strlen, verbose)) { 432 return false; 433 } 434 } 435 } 436 437 printf(" Verifying strlen does not read past end of string.\n"); 438 439 // In order to verify that strlen is not reading past the end of the 440 // string, create strings that end near unreadable memory. 441 long pagesize = sysconf(_SC_PAGE_SIZE); 442 char *memory = (char*)memalign(pagesize, 2 * pagesize); 443 if (memory == NULL) { 444 perror("Unable to allocate memory.\n"); 445 return false; 446 } 447 448 // Make the second page unreadable and unwritable. 449 if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) { 450 perror("Unable to set protection of page.\n"); 451 return false; 452 } 453 454 size_t max_size = pagesize < MAX_STRLEN_TEST_SIZE ? pagesize-1 : MAX_STRLEN_TEST_SIZE; 455 for (long i = 0; i < pagesize; i++) { 456 memory[i] = (char)(32 + (i % 96)); 457 } 458 459 size_t len; 460 for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) { 461 for (size_t j = 0; j <= max_size; j++) { 462 string = &memory[pagesize-j-1]; 463 string[j] = '\0'; 464 465 if (verbose) { 466 printf("Testing size %d overread, align=%p[%d,%d]\n", 467 j, string, aligns[i][0], aligns[i][1]); 468 } 469 len = test_strlen(string); 470 if (len != j) { 471 printf(" Failed at size %u, returned %u, align=%p[%d,%d]\n", 472 j, len, string, aligns[i][0], aligns[i][1]); 473 return false; 474 } 475 string[j] = (char)(32 + (j % 96)); 476 } 477 } 478 479 printf(" All tests pass.\n"); 480 481 return true; 482} 483 484bool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n), 485 bool verbose) { 486 // Allocate two large buffers to hold the dst and src. 487 uint8_t *dst = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE)); 488 uint8_t *src = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE)); 489 if (dst == NULL || src == NULL) { 490 perror("Unable to allocate memory.\n"); 491 return false; 492 } 493 494 // Set the source to a known pattern once. The assumption is that the 495 // memcpy is not so broken that it will write in to the source buffer. 496 // However, do not write zeroes into the source so a very quick can be 497 // made to verify the source has not been modified. 498 for (int i = 0; i < MAX_MEMCPY_BUFFER_SIZE; i++) { 499 src[i] = i % 256; 500 if (src[i] == 0) { 501 src[i] = 0xaa; 502 } 503 } 504 505 int aligns[][4] = { 506 // Src and dst use pointers returned by malloc. 507 { 0, 0, 0, 0 }, 508 509 // Src and dst at same alignment. 510 { 1, 0, 1, 0 }, 511 { 2, 0, 2, 0 }, 512 { 4, 0, 4, 0 }, 513 { 8, 0, 8, 0 }, 514 { 16, 0, 16, 0 }, 515 { 32, 0, 32, 0 }, 516 { 64, 0, 64, 0 }, 517 { 128, 0, 128, 0 }, 518 519 // Different alignments between src and dst. 520 { 8, 0, 4, 0 }, 521 { 4, 0, 8, 0 }, 522 { 16, 0, 4, 0 }, 523 { 4, 0, 16, 0 }, 524 525 // General unaligned cases. 526 { 4, 0, 4, 1 }, 527 { 4, 0, 4, 2 }, 528 { 4, 0, 4, 3 }, 529 { 4, 1, 4, 0 }, 530 { 4, 2, 4, 0 }, 531 { 4, 3, 4, 0 }, 532 533 // All non-word aligned cases. 534 { 4, 1, 4, 0 }, 535 { 4, 1, 4, 1 }, 536 { 4, 1, 4, 2 }, 537 { 4, 1, 4, 3 }, 538 539 { 4, 2, 4, 0 }, 540 { 4, 2, 4, 1 }, 541 { 4, 2, 4, 2 }, 542 { 4, 2, 4, 3 }, 543 544 { 4, 3, 4, 0 }, 545 { 4, 3, 4, 1 }, 546 { 4, 3, 4, 2 }, 547 { 4, 3, 4, 3 }, 548 549 { 2, 0, 4, 0 }, 550 { 4, 0, 2, 0 }, 551 { 2, 0, 2, 0 }, 552 553 // Invoke the unaligned case where the code needs to align dst to 0x10. 554 { 128, 1, 128, 4 }, 555 { 128, 1, 128, 8 }, 556 { 128, 1, 128, 12 }, 557 { 128, 1, 128, 16 }, 558 }; 559 560 printf(" Verifying variable sized copies at different alignments.\n"); 561 uint8_t *src_align, *dst_align; 562 for (size_t i = 0; i < sizeof(aligns)/sizeof(int[4]); i++) { 563 for (size_t len = 0; len <= MAX_MEMCPY_TEST_SIZE; len++) { 564 if (aligns[i][0]) { 565 src_align = (uint8_t*)getAlignedPtr(src+FENCEPOST_LENGTH, aligns[i][0], 566 aligns[i][1]); 567 dst_align = (uint8_t*)getAlignedPtr(dst+FENCEPOST_LENGTH, aligns[i][2], 568 aligns[i][3]); 569 } else { 570 src_align = src; 571 dst_align = dst; 572 } 573 574 if (verbose) { 575 printf("Testing size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 576 len, src_align, aligns[i][0], aligns[i][1], 577 dst_align, aligns[i][2], aligns[i][3]); 578 } 579 580 memset(dst_align, 0, len); 581 582 // Don't add a pre fencepost if we are using the value from the malloc. 583 if (dst_align != dst) { 584 setFencepost(&dst_align[-8]); 585 } 586 setFencepost(&dst_align[len]); 587 588 test_memcpy(dst_align, src_align, len); 589 590 for (size_t j = 0; j < len; j++) { 591 if (dst_align[j] != src_align[j] || !src_align[j]) { 592 if (!src_align[j]) { 593 printf(" src_align[%d] is 0, memcpy wrote into the source.\n", j); 594 } else { 595 printf(" mismatch at %d, expected %d found %d\n", j, 596 src_align[j], dst_align[j]); 597 } 598 printf(" Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 599 len, src_align, aligns[i][0], aligns[i][1], 600 dst_align, aligns[i][2], aligns[i][3]); 601 return false; 602 } 603 } 604 if (dst_align != dst && !verifyFencepost(&dst_align[-8])) { 605 printf(" wrote before the array.\n"); 606 printf(" Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 607 len, src_align, aligns[i][0], aligns[i][1], 608 dst_align, aligns[i][2], aligns[i][3]); 609 return false; 610 } 611 if (!verifyFencepost(&dst_align[len])) { 612 printf(" wrote past the end of the array.\n"); 613 printf(" Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 614 len, src_align, aligns[i][0], aligns[i][1], 615 dst_align, aligns[i][2], aligns[i][3]); 616 return false; 617 } 618 } 619 } 620 621 printf(" All tests pass.\n"); 622 623 return true; 624} 625 626bool runMemsetTest(void* (*test_memset)(void *s, int c, size_t n), 627 bool verbose) { 628 // Allocate one large buffer to hold the dst. 629 uint8_t *buf = reinterpret_cast<uint8_t*>(malloc(MAX_MEMSET_BUFFER_SIZE)); 630 if (buf == NULL) { 631 perror("Unable to allocate memory.\n"); 632 return false; 633 } 634 635 int aligns[][2] = { 636 // Use malloc return values unaltered. 637 { 0, 0 }, 638 639 // Different alignments. 640 { 1, 0 }, 641 { 2, 0 }, 642 { 4, 0 }, 643 { 8, 0 }, 644 { 16, 0 }, 645 { 32, 0 }, 646 { 64, 0 }, 647 648 // Different alignments between src and dst. 649 { 8, 1 }, 650 { 8, 2 }, 651 { 8, 3 }, 652 { 8, 4 }, 653 { 8, 5 }, 654 { 8, 6 }, 655 { 8, 7 }, 656 }; 657 658 printf(" Verifying variable sized memsets at different alignments.\n"); 659 uint8_t *buf_align; 660 for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) { 661 for (size_t len = 0; len <= MAX_MEMSET_TEST_SIZE; len++) { 662 if (aligns[i]) { 663 buf_align = (uint8_t*)getAlignedPtr(buf+FENCEPOST_LENGTH, aligns[i][0], 664 aligns[i][1]); 665 } else { 666 buf_align = buf; 667 } 668 669 if (verbose) { 670 printf("Testing size %d, buf_align=%p[%d,%d]\n", 671 len, buf_align, aligns[i][0], aligns[i][1]); 672 } 673 674 // Set the buffer to all zero without memset since it might be the 675 // function we are testing. 676 for (size_t j = 0; j < len; j++) { 677 buf_align[j] = 0; 678 } 679 680 // Don't add a pre fencepost if we are using the value from the malloc. 681 if (buf_align != buf) { 682 setFencepost(&buf_align[-8]); 683 } 684 setFencepost(&buf_align[len]); 685 686 int value = (len % 255) + 1; 687 test_memset(buf_align, value, len); 688 689 for (size_t j = 0; j < len; j++) { 690 if (buf_align[j] != value) { 691 printf(" Failed at size %d[%d,%d!=%d], buf_align=%p[%d,%d]\n", 692 len, j, buf_align[j], value, buf_align, aligns[i][0], 693 aligns[i][1]); 694 return false; 695 } 696 } 697 if (buf_align != buf && !verifyFencepost(&buf_align[-8])) { 698 printf(" wrote before the beginning of the array.\n"); 699 printf(" Failed at size %d, buf_align=%p[%d,%d]\n", 700 len, buf_align, aligns[i][0], aligns[i][1]); 701 return false; 702 } 703 if (!verifyFencepost(&buf_align[len])) { 704 printf(" wrote after the end of the array.\n"); 705 printf(" Failed at size %d, buf_align=%p[%d,%d]\n", 706 len, buf_align, aligns[i][0], aligns[i][1]); 707 return false; 708 } 709 } 710 } 711 712 printf(" All tests pass.\n"); 713 714 return true; 715} 716 717int main(int argc, char **argv) { 718 bool verbose = false; 719 if (argc == 2 && strcmp(argv[1], "-v") == 0) { 720 verbose = true; 721 } 722 723 bool tests_passing = true; 724 725 printf("Testing strcmp...\n"); 726 tests_passing = runStrcmpTest(strcmp, verbose) && tests_passing; 727 728 printf("Testing memcpy...\n"); 729 tests_passing = runMemcpyTest(memcpy, verbose) && tests_passing; 730 731 printf("Testing memset...\n"); 732 tests_passing = runMemsetTest(memset, verbose) && tests_passing; 733 734 printf("Testing strlen...\n"); 735 tests_passing = runStrlenTest(strlen, verbose) && tests_passing; 736 737 return (tests_passing ? 0 : 1); 738} 739