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. 23 extern "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_STRING_TEST_SIZE 1024 35 #define MAX_STRING_BUFFER_SIZE (3 * MAX_STRING_TEST_SIZE) 36 37 #define MAX_STRCAT_DST_SIZE 32 38 39 const int kStringAligns[][4] = { 40 // All zeroes to use the values returned from malloc. 41 { 0, 0, 0, 0 }, 42 43 { 1, 0, 1, 0 }, 44 { 2, 0, 2, 0 }, 45 { 4, 0, 4, 0 }, 46 { 8, 0, 8, 0 }, 47 48 { 8, 0, 4, 0 }, 49 { 4, 0, 8, 0 }, 50 51 { 8, 0, 8, 1 }, 52 { 8, 0, 8, 2 }, 53 { 8, 0, 8, 3 }, 54 { 8, 1, 8, 0 }, 55 { 8, 2, 8, 0 }, 56 { 8, 3, 8, 0 }, 57 58 { 4, 0, 4, 1 }, 59 { 4, 0, 4, 2 }, 60 { 4, 0, 4, 3 }, 61 { 4, 1, 4, 0 }, 62 { 4, 2, 4, 0 }, 63 { 4, 3, 4, 0 }, 64 }; 65 66 #define STRING_ALIGN_LEN (sizeof(kStringAligns)/sizeof(int[4])) 67 68 // Return a pointer into the current string with the specified alignment. 69 void *getAlignedPtr(void *orig_ptr, int alignment, int or_mask) { 70 uint64_t ptr = reinterpret_cast<uint64_t>(orig_ptr); 71 if (alignment > 0) { 72 // When setting the alignment, set it to exactly the alignment chosen. 73 // The pointer returned will be guaranteed not to be aligned to anything 74 // more than that. 75 ptr += alignment - (ptr & (alignment - 1)); 76 ptr |= alignment | or_mask; 77 } 78 79 return reinterpret_cast<void*>(ptr); 80 } 81 82 char *setString(char *str, size_t size) { 83 for (size_t i = 0; i < size; i++) { 84 str[i] = (char)(32 + (i % 96)); 85 } 86 str[size] = '\0'; 87 88 return str; 89 } 90 91 char *allocateString() { 92 char *str = reinterpret_cast<char*>(malloc(MAX_STRING_BUFFER_SIZE+1)); 93 if (!str) { 94 return NULL; 95 } 96 97 return setString(str, MAX_STRING_BUFFER_SIZE); 98 } 99 100 void setFencepost(uint8_t *buffer) { 101 for (int i = 0; i < FENCEPOST_LENGTH; i += 2) { 102 buffer[i] = 0xde; 103 buffer[i+1] = 0xad; 104 } 105 } 106 107 bool verifyFencepost(uint8_t *buffer) { 108 for (int i = 0; i < FENCEPOST_LENGTH; i += 2) { 109 if (buffer[i] != 0xde || buffer[i+1] != 0xad) { 110 uint8_t expected_value; 111 if (buffer[i] == 0xde) { 112 i++; 113 expected_value = 0xad; 114 } else { 115 expected_value = 0xde; 116 } 117 printf(" mismatch at fencepost[%d], expected %d found %d\n", 118 i, expected_value, buffer[i]); 119 return false; 120 } 121 } 122 return true; 123 } 124 125 bool doStrcmpExpectEqual(char *string1, char *string2, const int align[4], 126 int (*test_strcmp)(const char *s1, const char *s2), 127 bool verbose) { 128 char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]); 129 char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]); 130 131 for (size_t i = 0; i < MAX_STRING_TEST_SIZE; i++) { 132 for (size_t j = 0; j < i; j++) { 133 align_str1[j] = (char)(32 + (j % 96)); 134 align_str2[j] = align_str1[j]; 135 } 136 align_str1[i] = '\0'; 137 align_str2[i] = '\0'; 138 139 // Set the characters after the string terminates to different values 140 // to verify that the strcmp is not over checking. 141 for (size_t j = i+1; j < i+64; j++) { 142 align_str1[j] = (char)(32 + j); 143 align_str2[j] = (char)(40 + j); 144 } 145 146 if (verbose) { 147 printf("Testing size %d, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n", 148 i, align_str1, align[0], align[1], align_str2, align[2], align[3]); 149 } 150 151 if (test_strcmp(align_str1, align_str2) != 0) { 152 printf(" Failed at size %d, src1 %p, src2 %p\n", 153 i, align_str1, align_str2); 154 return false; 155 } 156 } 157 158 return true; 159 } 160 161 bool doStrcmpExpectDiff(char *string1, char *string2, const int diff_align[2], 162 const int align[4], char diff_char, 163 int (*test_strcmp)(const char *s1, const char *s2), 164 bool verbose) { 165 char *align_str1 = (char*)getAlignedPtr(string1, align[0], align[1]); 166 char *align_str2 = (char*)getAlignedPtr(string2, align[2], align[3]); 167 168 for (int i = 0; i < MAX_STRING_TEST_SIZE; i++) { 169 // Use valid ascii characters, no unprintables characters. 170 align_str1[i] = (char)(32 + (i % 96)); 171 if (align_str1[i] == diff_char) { 172 // Assumes that one less than the diff character is still a valid 173 // character. 174 align_str1[i] = diff_char-1; 175 } 176 align_str2[i] = align_str1[i]; 177 } 178 align_str1[MAX_STRING_TEST_SIZE] = '\0'; 179 align_str2[MAX_STRING_TEST_SIZE] = '\0'; 180 181 // Quick check to make sure that the strcmp knows that everything is 182 // equal. If it's so broken that it already thinks the strings are 183 // different, then there is no point running any of the other tests. 184 if (test_strcmp(align_str1, align_str2) != 0) { 185 printf(" strcmp is too broken to do difference testing.\n"); 186 return false; 187 } 188 189 // Get a pointer into the string at the specified alignment. 190 char *bad = (char*)getAlignedPtr(align_str1+MAX_STRING_TEST_SIZE/2, 191 diff_align[0], diff_align[1]); 192 193 char saved_char = bad[0]; 194 bad[0] = diff_char; 195 196 if (verbose) { 197 printf("Testing difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n", 198 align_str1, align[0], align[1], align_str2, align[2], align[3]); 199 } 200 if (test_strcmp(align_str1, align_str2) == 0) { 201 printf(" Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n", 202 MAX_STRING_TEST_SIZE, align_str1, align_str2, bad); 203 return false; 204 } 205 bad[0] = saved_char; 206 207 // Re-verify that something hasn't gone horribly wrong. 208 if (test_strcmp(align_str1, align_str2) != 0) { 209 printf(" strcmp is too broken to do difference testing.\n"); 210 return false; 211 } 212 213 bad = (char*)getAlignedPtr(align_str2+MAX_STRING_TEST_SIZE/2, diff_align[0], 214 diff_align[1]); 215 bad[0] = diff_char; 216 217 if (verbose) { 218 printf("Testing reverse difference, align_str1=%p[%d,%d], align_str2=%p[%d,%d]\n", 219 align_str1, align[0], align[1], align_str2, align[2], align[3]); 220 } 221 if (test_strcmp(align_str1, align_str2) == 0) { 222 printf(" Did not miscompare at size %d, src1 %p, src2 %p, diff %p\n", 223 MAX_STRING_TEST_SIZE, align_str1, align_str2, bad); 224 return false; 225 } 226 227 return true; 228 } 229 230 bool doStrcmpCheckRead(int (*test_strcmp)(const char *s1, const char *s2), 231 bool verbose) { 232 // In order to verify that the strcmp is not reading past the end of the 233 // string, create some strings that end near unreadable memory. 234 long pagesize = sysconf(_SC_PAGE_SIZE); 235 char *memory = (char*)memalign(pagesize, 2 * pagesize); 236 if (memory == NULL) { 237 perror("Unable to allocate memory.\n"); 238 return false; 239 } 240 241 // Make the second page unreadable and unwritable. 242 if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) { 243 perror("Unable to set protection of page.\n"); 244 return false; 245 } 246 247 size_t max_size = pagesize < MAX_STRING_TEST_SIZE ? pagesize-1 : MAX_STRING_TEST_SIZE; 248 // Allocate an extra byte beyond the string terminator to allow us to 249 // extend the string to be larger than our protected string. 250 char *other_string = (char *)malloc(max_size+2); 251 if (other_string == NULL) { 252 perror("Unable to allocate memory.\n"); 253 return false; 254 } 255 char *string; 256 for (size_t i = 0; i <= max_size; i++) { 257 string = &memory[pagesize-i-1]; 258 for (size_t j = 0; j < i; j++) { 259 other_string[j] = (char)(32 + (j % 96)); 260 string[j] = other_string[j]; 261 } 262 other_string[i] = '\0'; 263 string[i] = '\0'; 264 265 if (verbose) { 266 printf("Testing size %d, strings equal.\n", i); 267 } 268 if (test_strcmp(other_string, string) != 0) { 269 printf(" Failed at size %d, src1 %p, src2 %p\n", i, other_string, string); 270 return false; 271 } 272 273 if (verbose) { 274 printf("Testing size %d, strings equal reverse strings.\n", i); 275 } 276 if (test_strcmp(string, other_string) != 0) { 277 printf(" Failed at size %d, src1 %p, src2 %p\n", i, string, other_string); 278 return false; 279 } 280 281 // Now make other_string longer than our protected string. 282 other_string[i] = '1'; 283 other_string[i+1] = '\0'; 284 285 if (verbose) { 286 printf("Testing size %d, strings not equal.\n", i); 287 } 288 if (test_strcmp(other_string, string) == 0) { 289 printf(" Failed at size %d, src1 %p, src2 %p\n", i, other_string, string); 290 return false; 291 } 292 293 if (verbose) { 294 printf("Testing size %d, strings not equal reverse the strings.\n", i); 295 } 296 if (test_strcmp(string, other_string) == 0) { 297 printf(" Failed at size %d, src1 %p, src2 %p\n", i, string, other_string); 298 return false; 299 } 300 } 301 return true; 302 } 303 304 bool runStrcmpTest(int (*test_strcmp)(const char *s1, const char *s2), 305 bool verbose) { 306 char *string1 = allocateString(); 307 char *string2 = allocateString(); 308 if (string1 == NULL || string2 == NULL) { 309 perror("Unable to allocate memory.\n"); 310 return false; 311 } 312 313 printf(" Verifying equal sized strings at different alignments.\n"); 314 for (size_t i = 0; i < STRING_ALIGN_LEN; i++) { 315 if (!doStrcmpExpectEqual(string1, string2, kStringAligns[i], test_strcmp, 316 verbose)) { 317 return false; 318 } 319 } 320 321 // Test the function finds strings with differences at specific locations. 322 const int diff_aligns[][2] = { 323 { 4, 0 }, 324 { 4, 1 }, 325 { 4, 2 }, 326 { 4, 3 }, 327 { 8, 0 }, 328 { 8, 1 }, 329 { 8, 2 }, 330 { 8, 3 }, 331 }; 332 printf(" Verifying different strings at different alignments.\n"); 333 for (size_t i = 0; i < sizeof(diff_aligns)/sizeof(int[2]); i++) { 334 // First loop put the string terminator at the chosen alignment. 335 for (size_t j = 0; j < STRING_ALIGN_LEN; j++) { 336 if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i], 337 kStringAligns[j], '\0', test_strcmp, verbose)) { 338 return false; 339 } 340 } 341 // Second loop put a different character at the chosen alignment. 342 // This character is guaranteed not to be in the original string. 343 for (size_t j = 0; j < STRING_ALIGN_LEN; j++) { 344 if (!doStrcmpExpectDiff(string1, string2, diff_aligns[i], 345 kStringAligns[j], '\0', test_strcmp, verbose)) { 346 return false; 347 } 348 } 349 } 350 351 printf(" Verifying strcmp does not read too many bytes.\n"); 352 if (!doStrcmpCheckRead(test_strcmp, verbose)) { 353 return false; 354 } 355 356 printf(" All tests pass.\n"); 357 358 return true; 359 } 360 361 bool doStrlenCheck(size_t size, char *string, int align, int or_mask, 362 size_t (*test_strlen)(const char *), bool verbose) { 363 char *aligned_string = reinterpret_cast<char*>(getAlignedPtr(string, align, or_mask)); 364 size_t len; 365 if (verbose) { 366 printf("Testing size %d, align=%p[%d,%d]\n", size, aligned_string, align, or_mask); 367 } 368 369 aligned_string[size] = '\0'; 370 len = test_strlen(aligned_string); 371 if (len != size) { 372 printf("Failed at size %d, length returned %u, align=%p[%d,%d]\n", 373 size, len, aligned_string, align, or_mask); 374 return false; 375 } 376 377 if (verbose) { 378 printf("Testing size %d with extra zeros after string, align=%p[%d,%d]\n", 379 size, aligned_string, align, or_mask); 380 } 381 382 for (size_t j = size+1; j <= size+16; j++) { 383 aligned_string[j] = '\0'; 384 } 385 386 len = test_strlen(aligned_string); 387 if (len != size) { 388 printf("Failed at size %d, length returned %u with zeroes after string, align=%p[%d,%d]\n", 389 size, len, aligned_string, align, or_mask); 390 return false; 391 } 392 393 for (size_t j = size; j <= size+16; j++) { 394 aligned_string[j] = (char)(32 + (j % 96)); 395 } 396 return true; 397 } 398 399 bool runStrlenTest(size_t (*test_strlen)(const char *), 400 bool verbose) { 401 char *string = allocateString(); 402 if (string == NULL) { 403 perror("Unable to allocate memory.\n"); 404 return false; 405 } 406 407 // Check different string alignments. All zeroes indicates that the 408 // unmodified malloc values should be used. 409 const int aligns[][2] = { 410 // All zeroes to use the values returned from malloc. 411 { 0, 0 }, 412 413 { 1, 0 }, 414 { 2, 0 }, 415 { 4, 0 }, 416 { 8, 0 }, 417 { 16, 0 }, 418 { 32, 0 }, 419 420 { 8, 1 }, 421 { 8, 2 }, 422 { 8, 3 }, 423 424 { 4, 1 }, 425 { 4, 2 }, 426 { 4, 3 }, 427 }; 428 429 printf(" Verifying string lengths at different alignments.\n"); 430 for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) { 431 for (size_t j = 0; j <= MAX_STRING_TEST_SIZE; j++) { 432 if (!doStrlenCheck(j, string, aligns[i][0], aligns[i][1], test_strlen, verbose)) { 433 return false; 434 } 435 } 436 } 437 438 printf(" Verifying strlen does not read past end of string.\n"); 439 440 // In order to verify that strlen is not reading past the end of the 441 // string, create strings that end near unreadable memory. 442 long pagesize = sysconf(_SC_PAGE_SIZE); 443 char *memory = (char*)memalign(pagesize, 2 * pagesize); 444 if (memory == NULL) { 445 perror("Unable to allocate memory.\n"); 446 return false; 447 } 448 449 // Make the second page unreadable and unwritable. 450 if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) { 451 perror("Unable to set protection of page.\n"); 452 return false; 453 } 454 455 size_t max_size = pagesize < MAX_STRING_TEST_SIZE ? pagesize-1 : MAX_STRING_TEST_SIZE; 456 for (long i = 0; i < pagesize; i++) { 457 memory[i] = (char)(32 + (i % 96)); 458 } 459 460 size_t len; 461 for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) { 462 for (size_t j = 0; j <= max_size; j++) { 463 string = &memory[pagesize-j-1]; 464 string[j] = '\0'; 465 466 if (verbose) { 467 printf("Testing size %d overread, align=%p[%d,%d]\n", 468 j, string, aligns[i][0], aligns[i][1]); 469 } 470 len = test_strlen(string); 471 if (len != j) { 472 printf(" Failed at size %u, returned %u, align=%p[%d,%d]\n", 473 j, len, string, aligns[i][0], aligns[i][1]); 474 return false; 475 } 476 string[j] = (char)(32 + (j % 96)); 477 } 478 } 479 480 printf(" All tests pass.\n"); 481 482 return true; 483 } 484 485 bool runStrcpyTest(char *(*test_strcpy)(char *, const char *), 486 bool verbose) { 487 char *src = allocateString(); 488 if (src == NULL) { 489 perror("Unable to allocate memory.\n"); 490 return false; 491 } 492 char *dst = allocateString(); 493 if (dst == NULL) { 494 perror("Unable to allocate memory.\n"); 495 return false; 496 } 497 498 printf(" Verifying string lengths at different alignments.\n"); 499 char *src_align; 500 char *dst_align; 501 char *dst_ret; 502 for (size_t i = 0; i < STRING_ALIGN_LEN; i++) { 503 for (size_t copy_len = 0; copy_len <= MAX_STRING_TEST_SIZE; copy_len++) { 504 if (kStringAligns[i][0]) { 505 src_align = reinterpret_cast<char*>(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1])); 506 dst_align = reinterpret_cast<char*>(getAlignedPtr(dst+FENCEPOST_LENGTH, kStringAligns[i][2], kStringAligns[i][3])); 507 } else { 508 src_align = src; 509 dst_align = dst; 510 } 511 setString(src_align, copy_len); 512 memset(dst_align, 0, copy_len+1); 513 514 if (dst_align != dst) { 515 setFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH])); 516 } 517 setFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+1])); 518 519 if (verbose) { 520 printf("Testing copy_len %u, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 521 copy_len, src_align, kStringAligns[i][0], kStringAligns[i][1], 522 dst_align, kStringAligns[i][2], kStringAligns[i][3]); 523 } 524 525 dst_ret = test_strcpy(dst_align, src_align); 526 if (dst_ret != dst_align) { 527 printf("copy_len %u returned incorrect value: expected %p, got %p\n", 528 copy_len, dst_align, dst_ret); 529 return false; 530 } 531 if (memcmp(src_align, dst_align, copy_len) != 0) { 532 printf("copy_len %u failed to copy properly: src and dst aren't equal\n", copy_len); 533 return false; 534 } 535 536 if (dst_align != dst && !verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]))) { 537 printf("copy_len %u fencepost before dst was overwritten\n", copy_len); 538 return false; 539 } 540 541 if (!verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+1]))) { 542 printf("copy_len %u fencepost at end of dst was overwritten\n", copy_len); 543 return false; 544 } 545 } 546 } 547 548 printf(" All tests pass.\n"); 549 550 return true; 551 } 552 553 bool runStrcatTest(char *(*test_strcat)(char *, const char *), 554 bool verbose) { 555 char *src = allocateString(); 556 if (src == NULL) { 557 perror("Unable to allocate memory.\n"); 558 return false; 559 } 560 char *dst = allocateString(); 561 if (dst == NULL) { 562 perror("Unable to allocate memory.\n"); 563 return false; 564 } 565 566 printf(" Verifying string lengths at different alignments.\n"); 567 char *src_align; 568 char *dst_align; 569 char *dst_ret; 570 for (size_t i = 0; i < STRING_ALIGN_LEN; i++) { 571 for (size_t dst_len = 0; dst_len <= MAX_STRCAT_DST_SIZE; dst_len++) { 572 for (size_t copy_len = 0; copy_len <= MAX_STRING_TEST_SIZE; copy_len++) { 573 if (kStringAligns[i][0]) { 574 src_align = reinterpret_cast<char*>(getAlignedPtr(src+FENCEPOST_LENGTH, kStringAligns[i][0], kStringAligns[i][1])); 575 dst_align = reinterpret_cast<char*>(getAlignedPtr(dst+FENCEPOST_LENGTH, kStringAligns[i][2], kStringAligns[i][3])); 576 } else { 577 src_align = src; 578 dst_align = dst; 579 } 580 setString(src_align, copy_len); 581 memset(dst_align, 'd', dst_len); 582 memset(dst_align+dst_len, 0, copy_len+1); 583 584 if (dst_align != dst) { 585 setFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH])); 586 } 587 setFencepost(reinterpret_cast<uint8_t*>(&dst_align[copy_len+dst_len+1])); 588 589 if (verbose) { 590 printf("Testing copy_len %u, dst_len %u, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 591 copy_len, dst_len, src_align, kStringAligns[i][0], kStringAligns[i][1], 592 dst_align, kStringAligns[i][2], kStringAligns[i][3]); 593 } 594 595 dst_ret = test_strcat(dst_align, src_align); 596 if (dst_ret != dst_align) { 597 printf("dst_len %u, copy_len %u returned incorrect value: expected %p, got %p\n", 598 dst_len, copy_len, dst_align, dst_ret); 599 return false; 600 } 601 for (size_t j = 0; j < dst_len; j++) { 602 if (dst_align[j] != 'd') { 603 printf("dst_len %u, copy_len %u: strcat overwrote dst string\n", 604 dst_len, copy_len); 605 return false; 606 } 607 } 608 if (memcmp(src_align, dst_align+dst_len, copy_len+1) != 0) { 609 printf("dst_len %u, copy_len %u failed to copy properly: src and dst aren't equal\n", 610 dst_len, copy_len); 611 return false; 612 } 613 614 if (dst_align != dst && !verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[-FENCEPOST_LENGTH]))) { 615 return false; 616 } 617 618 if (!verifyFencepost(reinterpret_cast<uint8_t*>(&dst_align[dst_len+copy_len+1]))) { 619 return false; 620 } 621 } 622 } 623 } 624 625 printf(" All tests pass.\n"); 626 627 return true; 628 } 629 630 bool runMemcpyTest(void* (*test_memcpy)(void *dst, const void *src, size_t n), 631 bool verbose) { 632 uint8_t *dst = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE)); 633 uint8_t *src = reinterpret_cast<uint8_t*>(malloc(MAX_MEMCPY_BUFFER_SIZE)); 634 if (dst == NULL || src == NULL) { 635 perror("Unable to allocate memory.\n"); 636 return false; 637 } 638 639 // Set the source to a known pattern once. The assumption is that the 640 // memcpy is not so broken that it will write in to the source buffer. 641 // However, do not write zeroes into the source so a very quick can be 642 // made to verify the source has not been modified. 643 for (int i = 0; i < MAX_MEMCPY_BUFFER_SIZE; i++) { 644 src[i] = i % 256; 645 if (src[i] == 0) { 646 src[i] = 0xaa; 647 } 648 } 649 650 const int aligns[][4] = { 651 // Src and dst use pointers returned by malloc. 652 { 0, 0, 0, 0 }, 653 654 // Src and dst at same alignment. 655 { 1, 0, 1, 0 }, 656 { 2, 0, 2, 0 }, 657 { 4, 0, 4, 0 }, 658 { 8, 0, 8, 0 }, 659 { 16, 0, 16, 0 }, 660 { 32, 0, 32, 0 }, 661 { 64, 0, 64, 0 }, 662 { 128, 0, 128, 0 }, 663 664 // Different alignments between src and dst. 665 { 8, 0, 4, 0 }, 666 { 4, 0, 8, 0 }, 667 { 16, 0, 4, 0 }, 668 { 4, 0, 16, 0 }, 669 670 // General unaligned cases. 671 { 4, 0, 4, 1 }, 672 { 4, 0, 4, 2 }, 673 { 4, 0, 4, 3 }, 674 { 4, 1, 4, 0 }, 675 { 4, 2, 4, 0 }, 676 { 4, 3, 4, 0 }, 677 678 // All non-word aligned cases. 679 { 4, 1, 4, 0 }, 680 { 4, 1, 4, 1 }, 681 { 4, 1, 4, 2 }, 682 { 4, 1, 4, 3 }, 683 684 { 4, 2, 4, 0 }, 685 { 4, 2, 4, 1 }, 686 { 4, 2, 4, 2 }, 687 { 4, 2, 4, 3 }, 688 689 { 4, 3, 4, 0 }, 690 { 4, 3, 4, 1 }, 691 { 4, 3, 4, 2 }, 692 { 4, 3, 4, 3 }, 693 694 { 2, 0, 4, 0 }, 695 { 4, 0, 2, 0 }, 696 { 2, 0, 2, 0 }, 697 698 // Invoke the unaligned case where the code needs to align dst to 0x10. 699 { 128, 1, 128, 4 }, 700 { 128, 1, 128, 8 }, 701 { 128, 1, 128, 12 }, 702 { 128, 1, 128, 16 }, 703 }; 704 705 printf(" Verifying variable sized copies at different alignments.\n"); 706 uint8_t *src_align, *dst_align; 707 for (size_t i = 0; i < sizeof(aligns)/sizeof(int[4]); i++) { 708 for (size_t len = 0; len <= MAX_MEMCPY_TEST_SIZE; len++) { 709 if (aligns[i][0]) { 710 src_align = (uint8_t*)getAlignedPtr(src+FENCEPOST_LENGTH, aligns[i][0], 711 aligns[i][1]); 712 dst_align = (uint8_t*)getAlignedPtr(dst+FENCEPOST_LENGTH, aligns[i][2], 713 aligns[i][3]); 714 } else { 715 src_align = src; 716 dst_align = dst; 717 } 718 719 if (verbose) { 720 printf("Testing size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 721 len, src_align, aligns[i][0], aligns[i][1], 722 dst_align, aligns[i][2], aligns[i][3]); 723 } 724 725 memset(dst_align, 0, len); 726 727 // Don't add a pre fencepost if we are using the value from the malloc. 728 if (dst_align != dst) { 729 setFencepost(&dst_align[-8]); 730 } 731 setFencepost(&dst_align[len]); 732 733 test_memcpy(dst_align, src_align, len); 734 735 for (size_t j = 0; j < len; j++) { 736 if (dst_align[j] != src_align[j] || !src_align[j]) { 737 if (!src_align[j]) { 738 printf(" src_align[%d] is 0, memcpy wrote into the source.\n", j); 739 } else { 740 printf(" mismatch at %d, expected %d found %d\n", j, 741 src_align[j], dst_align[j]); 742 } 743 printf(" Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 744 len, src_align, aligns[i][0], aligns[i][1], 745 dst_align, aligns[i][2], aligns[i][3]); 746 return false; 747 } 748 } 749 if (dst_align != dst && !verifyFencepost(&dst_align[-8])) { 750 printf(" wrote before the array.\n"); 751 printf(" Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 752 len, src_align, aligns[i][0], aligns[i][1], 753 dst_align, aligns[i][2], aligns[i][3]); 754 return false; 755 } 756 if (!verifyFencepost(&dst_align[len])) { 757 printf(" wrote past the end of the array.\n"); 758 printf(" Failed at size %d, src_align=%p[%d,%d], dst_align=%p[%d,%d]\n", 759 len, src_align, aligns[i][0], aligns[i][1], 760 dst_align, aligns[i][2], aligns[i][3]); 761 return false; 762 } 763 } 764 } 765 766 printf(" All tests pass.\n"); 767 768 return true; 769 } 770 771 bool runMemsetTest(void* (*test_memset)(void *s, int c, size_t n), 772 bool verbose) { 773 uint8_t *buf = reinterpret_cast<uint8_t*>(malloc(MAX_MEMSET_BUFFER_SIZE)); 774 if (buf == NULL) { 775 perror("Unable to allocate memory.\n"); 776 return false; 777 } 778 779 const int aligns[][2] = { 780 // Use malloc return values unaltered. 781 { 0, 0 }, 782 783 // Different alignments. 784 { 1, 0 }, 785 { 2, 0 }, 786 { 4, 0 }, 787 { 8, 0 }, 788 { 16, 0 }, 789 { 32, 0 }, 790 { 64, 0 }, 791 792 // Different alignments between src and dst. 793 { 8, 1 }, 794 { 8, 2 }, 795 { 8, 3 }, 796 { 8, 4 }, 797 { 8, 5 }, 798 { 8, 6 }, 799 { 8, 7 }, 800 }; 801 802 printf(" Verifying variable sized memsets at different alignments.\n"); 803 uint8_t *buf_align; 804 for (size_t i = 0; i < sizeof(aligns)/sizeof(int[2]); i++) { 805 for (size_t len = 0; len <= MAX_MEMSET_TEST_SIZE; len++) { 806 if (aligns[i]) { 807 buf_align = (uint8_t*)getAlignedPtr(buf+FENCEPOST_LENGTH, aligns[i][0], 808 aligns[i][1]); 809 } else { 810 buf_align = buf; 811 } 812 813 if (verbose) { 814 printf("Testing size %d, buf_align=%p[%d,%d]\n", 815 len, buf_align, aligns[i][0], aligns[i][1]); 816 } 817 818 // Set the buffer to all zero without memset since it might be the 819 // function we are testing. 820 for (size_t j = 0; j < len; j++) { 821 buf_align[j] = 0; 822 } 823 824 // Don't add a pre fencepost if we are using the value from the malloc. 825 if (buf_align != buf) { 826 setFencepost(&buf_align[-8]); 827 } 828 setFencepost(&buf_align[len]); 829 830 int value = (len % 255) + 1; 831 test_memset(buf_align, value, len); 832 833 for (size_t j = 0; j < len; j++) { 834 if (buf_align[j] != value) { 835 printf(" Failed at size %d[%d,%d!=%d], buf_align=%p[%d,%d]\n", 836 len, j, buf_align[j], value, buf_align, aligns[i][0], 837 aligns[i][1]); 838 return false; 839 } 840 } 841 if (buf_align != buf && !verifyFencepost(&buf_align[-8])) { 842 printf(" wrote before the beginning of the array.\n"); 843 printf(" Failed at size %d, buf_align=%p[%d,%d]\n", 844 len, buf_align, aligns[i][0], aligns[i][1]); 845 return false; 846 } 847 if (!verifyFencepost(&buf_align[len])) { 848 printf(" wrote after the end of the array.\n"); 849 printf(" Failed at size %d, buf_align=%p[%d,%d]\n", 850 len, buf_align, aligns[i][0], aligns[i][1]); 851 return false; 852 } 853 } 854 } 855 856 printf(" All tests pass.\n"); 857 858 return true; 859 } 860 861 int main(int argc, char **argv) { 862 bool verbose = false; 863 if (argc == 2 && strcmp(argv[1], "-v") == 0) { 864 verbose = true; 865 } 866 867 bool tests_passing = true; 868 869 printf("Testing strcmp...\n"); 870 tests_passing = runStrcmpTest(strcmp, verbose) && tests_passing; 871 872 printf("Testing memcpy...\n"); 873 tests_passing = runMemcpyTest(memcpy, verbose) && tests_passing; 874 875 printf("Testing memset...\n"); 876 tests_passing = runMemsetTest(memset, verbose) && tests_passing; 877 878 printf("Testing strlen...\n"); 879 tests_passing = runStrlenTest(strlen, verbose) && tests_passing; 880 881 printf("Testing strcpy...\n"); 882 tests_passing = runStrcpyTest(strcpy, verbose) && tests_passing; 883 884 printf("Testing strcat...\n"); 885 tests_passing = runStrcatTest(strcat, verbose) && tests_passing; 886 887 return (tests_passing ? 0 : 1); 888 } 889