string_test.cpp revision 1468765f8ab81ae9e32638d25c14e1f5dd35da2b
1/* 2 * Copyright (C) 2012 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#define _GNU_SOURCE 1 18 19#include <string.h> 20 21#include <errno.h> 22#include <gtest/gtest.h> 23#include <malloc.h> 24#include <math.h> 25 26#include "buffer_tests.h" 27 28#if defined(__BIONIC__) 29#define STRLCPY_SUPPORTED 30#define STRLCAT_SUPPORTED 31#endif 32 33#define KB 1024 34#define SMALL 1*KB 35#define MEDIUM 4*KB 36#define LARGE 64*KB 37 38static int signum(int i) { 39 if (i < 0) { 40 return -1; 41 } else if (i > 0) { 42 return 1; 43 } 44 return 0; 45} 46 47TEST(string, strerror) { 48 // Valid. 49 ASSERT_STREQ("Success", strerror(0)); 50 ASSERT_STREQ("Operation not permitted", strerror(1)); 51 52 // Invalid. 53 ASSERT_STREQ("Unknown error -1", strerror(-1)); 54 ASSERT_STREQ("Unknown error 1234", strerror(1234)); 55} 56 57#if defined(__BIONIC__) 58static void* ConcurrentStrErrorFn(void*) { 59 bool equal = (strcmp("Unknown error 2002", strerror(2002)) == 0); 60 return reinterpret_cast<void*>(equal); 61} 62#endif // __BIONIC__ 63 64// glibc's strerror isn't thread safe, only its strsignal. 65TEST(string, strerror_concurrent) { 66#if defined(__BIONIC__) 67 const char* strerror1001 = strerror(1001); 68 ASSERT_STREQ("Unknown error 1001", strerror1001); 69 70 pthread_t t; 71 ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrErrorFn, NULL)); 72 void* result; 73 ASSERT_EQ(0, pthread_join(t, &result)); 74 ASSERT_TRUE(static_cast<bool>(result)); 75 76 ASSERT_STREQ("Unknown error 1001", strerror1001); 77#else // __BIONIC__ 78 GTEST_LOG_(INFO) << "Skipping test, requires a thread safe strerror."; 79#endif // __BIONIC__ 80} 81 82TEST(string, gnu_strerror_r) { 83 char buf[256]; 84 85 // Note that glibc doesn't necessarily write into the buffer. 86 87 // Valid. 88 ASSERT_STREQ("Success", strerror_r(0, buf, sizeof(buf))); 89#if defined(__BIONIC__) 90 ASSERT_STREQ("Success", buf); 91#endif 92 ASSERT_STREQ("Operation not permitted", strerror_r(1, buf, sizeof(buf))); 93#if defined(__BIONIC__) 94 ASSERT_STREQ("Operation not permitted", buf); 95#endif 96 97 // Invalid. 98 ASSERT_STREQ("Unknown error -1", strerror_r(-1, buf, sizeof(buf))); 99 ASSERT_STREQ("Unknown error -1", buf); 100 ASSERT_STREQ("Unknown error 1234", strerror_r(1234, buf, sizeof(buf))); 101 ASSERT_STREQ("Unknown error 1234", buf); 102 103 // Buffer too small. 104 errno = 0; 105 memset(buf, 0, sizeof(buf)); 106 ASSERT_EQ(buf, strerror_r(4567, buf, 2)); 107 ASSERT_STREQ("U", buf); 108 // The GNU strerror_r doesn't set errno (the POSIX one sets it to ERANGE). 109 ASSERT_EQ(0, errno); 110} 111 112TEST(string, strsignal) { 113 // A regular signal. 114 ASSERT_STREQ("Hangup", strsignal(1)); 115 116 // A real-time signal. 117 ASSERT_STREQ("Real-time signal 14", strsignal(SIGRTMIN + 14)); 118 // One of the signals the C library keeps to itself. 119 ASSERT_STREQ("Unknown signal 32", strsignal(__SIGRTMIN)); 120 121 // Errors. 122 ASSERT_STREQ("Unknown signal -1", strsignal(-1)); // Too small. 123 ASSERT_STREQ("Unknown signal 0", strsignal(0)); // Still too small. 124 ASSERT_STREQ("Unknown signal 1234", strsignal(1234)); // Too large. 125} 126 127static void* ConcurrentStrSignalFn(void*) { 128 bool equal = (strcmp("Unknown signal 2002", strsignal(2002)) == 0); 129 return reinterpret_cast<void*>(equal); 130} 131 132TEST(string, strsignal_concurrent) { 133 const char* strsignal1001 = strsignal(1001); 134 ASSERT_STREQ("Unknown signal 1001", strsignal1001); 135 136 pthread_t t; 137 ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrSignalFn, NULL)); 138 void* result; 139 ASSERT_EQ(0, pthread_join(t, &result)); 140 ASSERT_TRUE(static_cast<bool>(result)); 141 142 ASSERT_STREQ("Unknown signal 1001", strsignal1001); 143} 144 145// TODO: where did this number come from? 146#define ITER 500 147 148// For every length we want to test, vary and change alignment 149// of allocated memory, fill it with some values, calculate 150// expected result and then run function and compare what we got. 151// These tests contributed by Intel Corporation. 152// TODO: make these tests more intention-revealing and less random. 153template<class Character> 154class StringTestState { 155 public: 156 StringTestState(size_t MAX_LEN) : MAX_LEN(MAX_LEN), align1_index_(0), align2_index_(0) { 157 int max_alignment = 64; 158 159 // TODO: fix the tests to not sometimes use twice their specified "MAX_LEN". 160 glob_ptr = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment)); 161 glob_ptr1 = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment)); 162 glob_ptr2 = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment)); 163 164 InitLenArray(); 165 166 srandom(1234); 167 } 168 169 ~StringTestState() { 170 free(glob_ptr); 171 free(glob_ptr1); 172 free(glob_ptr2); 173 } 174 175 void BeginIterations() { 176 align1_index_ = 0; 177 align2_index_ = 0; 178 179 ResetPointers(); 180 } 181 182 bool HasNextIteration() { 183 return (align1_index_ != (alignments_size - 1) || align2_index_ != (alignments_size - 1)); 184 } 185 186 void NextIteration() { 187 if (align1_index_ == (alignments_size - 1) && align2_index_ == (alignments_size - 1)) { 188 return; 189 } 190 191 if (align1_index_ == (alignments_size - 1)) { 192 align1_index_ = 0; 193 align2_index_++; 194 } else { 195 align1_index_++; 196 } 197 198 ResetPointers(); 199 } 200 201 const size_t MAX_LEN; 202 Character *ptr, *ptr1, *ptr2; 203 size_t n; 204 size_t len[ITER + 1]; 205 206 private: 207 static size_t alignments[]; 208 static size_t alignments_size; 209 Character *glob_ptr, *glob_ptr1, *glob_ptr2; 210 size_t align1_index_, align2_index_; 211 212 // Calculate input lengths and fill state.len with them. 213 // Test small lengths with more density than big ones. Manually push 214 // smallest (0) and biggest (MAX_LEN) lengths. Avoid repeats. 215 // Return number of lengths to test. 216 void InitLenArray() { 217 n = 0; 218 len[n++] = 0; 219 for (size_t i = 1; i < ITER; ++i) { 220 size_t l = static_cast<size_t>(exp(log(static_cast<double>(MAX_LEN)) * i / ITER)); 221 if (l != len[n - 1]) { 222 len[n++] = l; 223 } 224 } 225 len[n++] = MAX_LEN; 226 } 227 228 void ResetPointers() { 229 if (align1_index_ == alignments_size || align2_index_ == alignments_size) { 230 ptr = ptr1 = ptr2 = nullptr; 231 } else { 232 ptr = glob_ptr + alignments[align1_index_]; 233 ptr1 = glob_ptr1 + alignments[align1_index_]; 234 ptr2 = glob_ptr2 + alignments[align2_index_]; 235 } 236 } 237}; 238 239template<class Character> 240size_t StringTestState<Character>::alignments[] = { 24, 32, 16, 48, 0, 1, 2, 3, 4, 5, 6, 7, 11 }; 241 242template<class Character> 243size_t StringTestState<Character>::alignments_size = sizeof(alignments)/sizeof(size_t); 244 245TEST(string, strcat) { 246 StringTestState<char> state(SMALL); 247 for (size_t i = 1; i < state.n; i++) { 248 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 249 memset(state.ptr2, '\2', state.MAX_LEN); 250 state.ptr2[state.MAX_LEN - 1] = '\0'; 251 memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN); 252 253 memset(state.ptr1, 'L', state.len[i]); 254 state.ptr1[random() % state.len[i]] = '\0'; 255 state.ptr1[state.len[i] - 1] = '\0'; 256 257 strcpy(state.ptr + state.MAX_LEN - 1, state.ptr1); 258 259 EXPECT_TRUE(strcat(state.ptr2, state.ptr1) == state.ptr2); 260 EXPECT_TRUE(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN) == 0); 261 } 262 } 263} 264 265// one byte target with "\0" source 266TEST(string, strcpy2) { 267 char buf[1]; 268 char* orig = strdup(""); 269 ASSERT_EQ(buf, strcpy(buf, orig)); 270 ASSERT_EQ('\0', buf[0]); 271 free(orig); 272} 273 274// multibyte target where we under fill target 275TEST(string, strcpy3) { 276 char buf[10]; 277 char* orig = strdup("12345"); 278 memset(buf, 'A', sizeof(buf)); 279 ASSERT_EQ(buf, strcpy(buf, orig)); 280 ASSERT_STREQ("12345", buf); 281 ASSERT_EQ('A', buf[6]); 282 ASSERT_EQ('A', buf[7]); 283 ASSERT_EQ('A', buf[8]); 284 ASSERT_EQ('A', buf[9]); 285 free(orig); 286} 287 288// multibyte target where we fill target exactly 289TEST(string, strcpy4) { 290 char buf[10]; 291 char* orig = strdup("123456789"); 292 memset(buf, 'A', sizeof(buf)); 293 ASSERT_EQ(buf, strcpy(buf, orig)); 294 ASSERT_STREQ("123456789", buf); 295 free(orig); 296} 297 298// one byte target with "\0" source 299TEST(string, stpcpy2) { 300 char buf[1]; 301 char* orig = strdup(""); 302 ASSERT_EQ(buf, stpcpy(buf, orig)); 303 ASSERT_EQ('\0', buf[0]); 304 free(orig); 305} 306 307// multibyte target where we under fill target 308TEST(string, stpcpy3) { 309 char buf[10]; 310 char* orig = strdup("12345"); 311 memset(buf, 'A', sizeof(buf)); 312 ASSERT_EQ(buf+strlen(orig), stpcpy(buf, orig)); 313 ASSERT_STREQ("12345", buf); 314 ASSERT_EQ('A', buf[6]); 315 ASSERT_EQ('A', buf[7]); 316 ASSERT_EQ('A', buf[8]); 317 ASSERT_EQ('A', buf[9]); 318 free(orig); 319} 320 321// multibyte target where we fill target exactly 322TEST(string, stpcpy4) { 323 char buf[10]; 324 char* orig = strdup("123456789"); 325 memset(buf, 'A', sizeof(buf)); 326 ASSERT_EQ(buf+strlen(orig), stpcpy(buf, orig)); 327 ASSERT_STREQ("123456789", buf); 328 free(orig); 329} 330 331TEST(string, strcat2) { 332 char buf[10]; 333 memset(buf, 'A', sizeof(buf)); 334 buf[0] = 'a'; 335 buf[1] = '\0'; 336 char* res = strcat(buf, "01234"); 337 ASSERT_EQ(buf, res); 338 ASSERT_STREQ("a01234", buf); 339 ASSERT_EQ('A', buf[7]); 340 ASSERT_EQ('A', buf[8]); 341 ASSERT_EQ('A', buf[9]); 342} 343 344TEST(string, strcat3) { 345 char buf[10]; 346 memset(buf, 'A', sizeof(buf)); 347 buf[0] = 'a'; 348 buf[1] = '\0'; 349 char* res = strcat(buf, "01234567"); 350 ASSERT_EQ(buf, res); 351 ASSERT_STREQ("a01234567", buf); 352} 353 354TEST(string, strncat2) { 355 char buf[10]; 356 memset(buf, 'A', sizeof(buf)); 357 buf[0] = 'a'; 358 buf[1] = '\0'; 359 char* res = strncat(buf, "01234", sizeof(buf) - strlen(buf) - 1); 360 ASSERT_EQ(buf, res); 361 ASSERT_STREQ("a01234", buf); 362 ASSERT_EQ('A', buf[7]); 363 ASSERT_EQ('A', buf[8]); 364 ASSERT_EQ('A', buf[9]); 365} 366 367TEST(string, strncat3) { 368 char buf[10]; 369 memset(buf, 'A', sizeof(buf)); 370 buf[0] = 'a'; 371 buf[1] = '\0'; 372 char* res = strncat(buf, "0123456789", 5); 373 ASSERT_EQ(buf, res); 374 ASSERT_STREQ("a01234", buf); 375 ASSERT_EQ('A', buf[7]); 376 ASSERT_EQ('A', buf[8]); 377 ASSERT_EQ('A', buf[9]); 378} 379 380TEST(string, strncat4) { 381 char buf[10]; 382 memset(buf, 'A', sizeof(buf)); 383 buf[0] = 'a'; 384 buf[1] = '\0'; 385 char* res = strncat(buf, "01234567", 8); 386 ASSERT_EQ(buf, res); 387 ASSERT_STREQ("a01234567", buf); 388} 389 390TEST(string, strncat5) { 391 char buf[10]; 392 memset(buf, 'A', sizeof(buf)); 393 buf[0] = 'a'; 394 buf[1] = '\0'; 395 char* res = strncat(buf, "01234567", 9); 396 ASSERT_EQ(buf, res); 397 ASSERT_STREQ("a01234567", buf); 398} 399 400TEST(string, strchr_with_0) { 401 char buf[10]; 402 const char* s = "01234"; 403 memcpy(buf, s, strlen(s) + 1); 404 EXPECT_TRUE(strchr(buf, '\0') == (buf + strlen(s))); 405} 406 407TEST(string, strchr_multiple) { 408 char str[128]; 409 memset(str, 'a', sizeof(str) - 1); 410 str[sizeof(str)-1] = '\0'; 411 412 // Verify that strchr finds the first occurrence of 'a' in a string 413 // filled with 'a' characters. Iterate over the string putting 414 // non 'a' characters at the front of the string during each iteration 415 // and continue to verify that strchr can find the first occurrence 416 // properly. The idea is to cover all possible alignments of the location 417 // of the first occurrence of the 'a' character and which includes 418 // other 'a' characters close by. 419 for (size_t i = 0; i < sizeof(str) - 1; i++) { 420 EXPECT_EQ(&str[i], strchr(str, 'a')); 421 str[i] = 'b'; 422 } 423} 424 425TEST(string, strchr) { 426 int seek_char = 'R'; 427 428 StringTestState<char> state(SMALL); 429 for (size_t i = 1; i < state.n; i++) { 430 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 431 if (~seek_char > 0) { 432 memset(state.ptr1, ~seek_char, state.len[i]); 433 } else { 434 memset(state.ptr1, '\1', state.len[i]); 435 } 436 state.ptr1[state.len[i] - 1] = '\0'; 437 438 size_t pos = random() % state.MAX_LEN; 439 char* expected; 440 if (pos >= state.len[i] - 1) { 441 if (seek_char == 0) { 442 expected = state.ptr1 + state.len[i] - 1; 443 } else { 444 expected = NULL; 445 } 446 } else { 447 state.ptr1[pos] = seek_char; 448 expected = state.ptr1 + pos; 449 } 450 451 ASSERT_TRUE(strchr(state.ptr1, seek_char) == expected); 452 } 453 } 454} 455 456TEST(string, strcmp) { 457 StringTestState<char> state(SMALL); 458 for (size_t i = 1; i < state.n; i++) { 459 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 460 memset(state.ptr1, 'v', state.MAX_LEN); 461 memset(state.ptr2, 'n', state.MAX_LEN); 462 state.ptr1[state.len[i] - 1] = '\0'; 463 state.ptr2[state.len[i] - 1] = '\0'; 464 465 size_t pos = 1 + (random() % (state.MAX_LEN - 1)); 466 int actual; 467 int expected; 468 if (pos >= state.len[i] - 1) { 469 memcpy(state.ptr1, state.ptr2, state.len[i]); 470 expected = 0; 471 actual = strcmp(state.ptr1, state.ptr2); 472 } else { 473 memcpy(state.ptr1, state.ptr2, pos); 474 if (state.ptr1[pos] > state.ptr2[pos]) { 475 expected = 1; 476 } else if (state.ptr1[pos] == state.ptr2[pos]) { 477 state.ptr1[pos + 1] = '\0'; 478 state.ptr2[pos + 1] = '\0'; 479 expected = 0; 480 } else { 481 expected = -1; 482 } 483 actual = strcmp(state.ptr1, state.ptr2); 484 } 485 486 ASSERT_EQ(expected, signum(actual)); 487 } 488 } 489} 490 491TEST(string, stpcpy) { 492 StringTestState<char> state(SMALL); 493 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 494 size_t pos = random() % state.MAX_LEN; 495 496 memset(state.ptr1, '\2', pos); 497 state.ptr1[pos] = '\0'; 498 state.ptr1[state.MAX_LEN - 1] = '\0'; 499 500 memcpy(state.ptr, state.ptr1, state.MAX_LEN); 501 502 memset(state.ptr2, '\1', state.MAX_LEN); 503 state.ptr2[state.MAX_LEN - 1] = '\0'; 504 505 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN); 506 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1); 507 state.ptr[2 * state.MAX_LEN - 1] = '\0'; 508 509 ASSERT_TRUE(stpcpy(state.ptr2, state.ptr1) == state.ptr2 + strlen(state.ptr1)); 510 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 || 511 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0)); 512 } 513} 514 515TEST(string, strcpy) { 516 StringTestState<char> state(SMALL); 517 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 518 size_t pos = random() % state.MAX_LEN; 519 520 memset(state.ptr1, '\2', pos); 521 state.ptr1[pos] = '\0'; 522 state.ptr1[state.MAX_LEN - 1] = '\0'; 523 524 memcpy(state.ptr, state.ptr1, state.MAX_LEN); 525 526 memset(state.ptr2, '\1', state.MAX_LEN); 527 state.ptr2[state.MAX_LEN - 1] = '\0'; 528 529 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN); 530 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1); 531 state.ptr[2 * state.MAX_LEN - 1] = '\0'; 532 533 ASSERT_TRUE(strcpy(state.ptr2, state.ptr1) == state.ptr2); 534 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 || 535 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0)); 536 } 537} 538 539TEST(string, strlcat) { 540#if defined(STRLCAT_SUPPORTED) 541 StringTestState<char> state(SMALL); 542 for (size_t i = 0; i < state.n; i++) { 543 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 544 memset(state.ptr2, '\2', state.MAX_LEN + state.len[i]); 545 state.ptr2[state.MAX_LEN - 1] = '\0'; 546 memcpy(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]); 547 548 size_t pos = random() % state.MAX_LEN; 549 memset(state.ptr1, '\3', pos); 550 state.ptr1[pos] = '\0'; 551 if (pos < state.len[i]) { 552 memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, pos + 1); 553 } else { 554 memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, state.len[i]); 555 state.ptr[state.MAX_LEN + state.len[i] - 1] = '\0'; 556 } 557 558 strlcat(state.ptr2, state.ptr1, state.MAX_LEN + state.len[i]); 559 560 ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0); 561 } 562 } 563#else 564 GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform."; 565#endif 566} 567 568TEST(string, strlcpy) { 569#if defined(STRLCPY_SUPPORTED) 570 StringTestState<char> state(SMALL); 571 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 572 int rand = 'O'; 573 memset(state.ptr1, rand, state.MAX_LEN); 574 575 size_t pos = random() % state.MAX_LEN; 576 if (pos < state.MAX_LEN) { 577 state.ptr1[pos] = '\0'; 578 } 579 memcpy(state.ptr, state.ptr1, state.MAX_LEN); 580 581 memset(state.ptr2, 'I', state.MAX_LEN); 582 memcpy(state.ptr + state.MAX_LEN, state.ptr2, state.MAX_LEN); 583 584 if (pos > state.MAX_LEN - 1) { 585 memcpy(state.ptr + state.MAX_LEN, state.ptr1, state.MAX_LEN); 586 state.ptr[2 * state.MAX_LEN - 1] = '\0'; 587 } else { 588 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1); 589 } 590 591 ASSERT_EQ(strlcpy(state.ptr2, state.ptr1, state.MAX_LEN), strlen(state.ptr1)); 592 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) || 593 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0)); 594 } 595#else 596 GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform."; 597#endif 598} 599 600TEST(string, strncat) { 601 StringTestState<char> state(SMALL); 602 for (size_t i = 1; i < state.n; i++) { 603 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 604 memset(state.ptr2, '\2', state.MAX_LEN); 605 state.ptr2[state.MAX_LEN - 1] = '\0'; 606 memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN); 607 608 memset(state.ptr1, 'I', state.len[i]); 609 state.ptr1[random() % state.len[i]] = '\0'; 610 state.ptr1[state.len[i] - 1] = '\0'; 611 612 size_t pos = strlen(state.ptr1); 613 614 size_t actual = random() % state.len[i]; 615 strncpy(state.ptr + state.MAX_LEN - 1, state.ptr1, std::min(actual, pos)); 616 state.ptr[state.MAX_LEN + std::min(actual, pos) - 1] = '\0'; 617 618 ASSERT_TRUE(strncat(state.ptr2, state.ptr1, actual) == state.ptr2); 619 ASSERT_EQ(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN), 0); 620 } 621 } 622} 623 624TEST(string, strncmp) { 625 StringTestState<char> state(SMALL); 626 for (size_t i = 1; i < state.n; i++) { 627 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 628 memset(state.ptr1, 'v', state.MAX_LEN); 629 memset(state.ptr2, 'n', state.MAX_LEN); 630 state.ptr1[state.len[i] - 1] = '\0'; 631 state.ptr2[state.len[i] - 1] = '\0'; 632 633 size_t pos = 1 + (random() % (state.MAX_LEN - 1)); 634 int actual; 635 int expected; 636 if (pos >= state.len[i] - 1) { 637 memcpy(state.ptr1, state.ptr2, state.len[i]); 638 expected = 0; 639 actual = strncmp(state.ptr1, state.ptr2, state.len[i]); 640 } else { 641 memcpy(state.ptr1, state.ptr2, pos); 642 if (state.ptr1[pos] > state.ptr2[pos]) { 643 expected = 1; 644 } else if (state.ptr1[pos] == state.ptr2[pos]) { 645 state.ptr1[pos + 1] = '\0'; 646 state.ptr2[pos + 1] = '\0'; 647 expected = 0; 648 } else { 649 expected = -1; 650 } 651 actual = strncmp(state.ptr1, state.ptr2, state.len[i]); 652 } 653 654 ASSERT_EQ(expected, signum(actual)); 655 } 656 } 657} 658 659TEST(string, stpncpy) { 660 StringTestState<char> state(SMALL); 661 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 662 memset(state.ptr1, 'J', state.MAX_LEN); 663 // Choose a random size for our src buffer. 664 size_t ptr1_len = random() % state.MAX_LEN; 665 state.ptr1[ptr1_len] = '\0'; 666 // Copy ptr1 into ptr, used to verify that ptr1 does not get modified. 667 memcpy(state.ptr, state.ptr1, state.MAX_LEN); 668 // Init ptr2 to a set value. 669 memset(state.ptr2, '\1', state.MAX_LEN); 670 671 // Choose a random amount of data to copy. 672 size_t copy_len = random() % state.MAX_LEN; 673 674 // Set the second half of ptr to the expected pattern in ptr2. 675 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN); 676 memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len); 677 size_t expected_end; 678 if (copy_len > ptr1_len) { 679 memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len); 680 expected_end = ptr1_len; 681 } else { 682 expected_end = copy_len; 683 } 684 685 ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len)); 686 687 // Verify ptr1 was not modified. 688 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN)); 689 // Verify ptr2 contains the expected data. 690 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN)); 691 } 692} 693 694TEST(string, strncpy) { 695 StringTestState<char> state(SMALL); 696 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 697 // Choose a random value to fill the string, except \0 (string terminator), 698 // or \1 (guarantees it's different from anything in ptr2). 699 memset(state.ptr1, 'K', state.MAX_LEN); 700 // Choose a random size for our src buffer. 701 size_t ptr1_len = random() % state.MAX_LEN; 702 state.ptr1[ptr1_len] = '\0'; 703 // Copy ptr1 into ptr, used to verify that ptr1 does not get modified. 704 memcpy(state.ptr, state.ptr1, state.MAX_LEN); 705 // Init ptr2 to a set value. 706 memset(state.ptr2, '\1', state.MAX_LEN); 707 708 // Choose a random amount of data to copy. 709 size_t copy_len = random() % state.MAX_LEN; 710 711 // Set the second half of ptr to the expected pattern in ptr2. 712 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN); 713 memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len); 714 size_t expected_end; 715 if (copy_len > ptr1_len) { 716 memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len); 717 expected_end = ptr1_len; 718 } else { 719 expected_end = copy_len; 720 } 721 722 ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len)); 723 724 // Verify ptr1 was not modified. 725 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN)); 726 // Verify ptr2 contains the expected data. 727 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN)); 728 } 729} 730 731TEST(string, strrchr) { 732 int seek_char = 'M'; 733 StringTestState<char> state(SMALL); 734 for (size_t i = 1; i < state.n; i++) { 735 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 736 if (~seek_char > 0) { 737 memset(state.ptr1, ~seek_char, state.len[i]); 738 } else { 739 memset(state.ptr1, '\1', state.len[i]); 740 } 741 state.ptr1[state.len[i] - 1] = '\0'; 742 743 size_t pos = random() % state.MAX_LEN; 744 char* expected; 745 if (pos >= state.len[i] - 1) { 746 if (seek_char == 0) { 747 expected = state.ptr1 + state.len[i] - 1; 748 } else { 749 expected = NULL; 750 } 751 } else { 752 state.ptr1[pos] = seek_char; 753 expected = state.ptr1 + pos; 754 } 755 756 ASSERT_TRUE(strrchr(state.ptr1, seek_char) == expected); 757 } 758 } 759} 760 761TEST(string, memchr) { 762 int seek_char = 'N'; 763 StringTestState<char> state(SMALL); 764 for (size_t i = 0; i < state.n; i++) { 765 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 766 memset(state.ptr1, ~seek_char, state.len[i]); 767 768 size_t pos = random() % state.MAX_LEN; 769 char* expected; 770 if (pos >= state.len[i]) { 771 expected = NULL; 772 } else { 773 state.ptr1[pos] = seek_char; 774 expected = state.ptr1 + pos; 775 } 776 777 ASSERT_TRUE(memchr(state.ptr1, seek_char, state.len[i]) == expected); 778 } 779 } 780} 781 782TEST(string, memchr_zero) { 783 uint8_t* buffer; 784 ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&buffer), 64, 64)); 785 memset(buffer, 10, 64); 786 ASSERT_TRUE(NULL == memchr(buffer, 5, 0)); 787 ASSERT_TRUE(NULL == memchr(buffer, 10, 0)); 788} 789 790TEST(string, memrchr) { 791 int seek_char = 'P'; 792 StringTestState<char> state(SMALL); 793 for (size_t i = 0; i < state.n; i++) { 794 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 795 memset(state.ptr1, ~seek_char, state.len[i]); 796 797 size_t pos = random() % state.MAX_LEN; 798 char* expected; 799 if (pos >= state.len[i]) { 800 expected = NULL; 801 } else { 802 state.ptr1[pos] = seek_char; 803 expected = state.ptr1 + pos; 804 } 805 806 ASSERT_TRUE(memrchr(state.ptr1, seek_char, state.len[i]) == expected); 807 } 808 } 809} 810 811TEST(string, memcmp) { 812 StringTestState<char> state(SMALL); 813 for (size_t i = 0; i < state.n; i++) { 814 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 815 int c1 = 'A'; 816 int c2 = 'N'; 817 memset(state.ptr1, c1, state.MAX_LEN); 818 memset(state.ptr2, c1, state.MAX_LEN); 819 820 int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]); 821 state.ptr2[pos] = c2; 822 823 int expected = (static_cast<int>(c1) - static_cast<int>(c2)); 824 int actual = memcmp(state.ptr1, state.ptr2, state.MAX_LEN); 825 826 ASSERT_EQ(signum(expected), signum(actual)); 827 } 828 } 829} 830 831TEST(string, wmemcmp) { 832 StringTestState<wchar_t> state(SMALL); 833 834 for (size_t i = 0; i < state.n; i++) { 835 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 836 long long mask = ((long long) 1 << 8 * sizeof(wchar_t)) - 1; 837 int c1 = rand() & mask; 838 int c2 = rand() & mask; 839 wmemset(state.ptr1, c1, state.MAX_LEN); 840 wmemset(state.ptr2, c1, state.MAX_LEN); 841 842 int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]); 843 state.ptr2[pos] = c2; 844 845 int expected = (static_cast<int>(c1) - static_cast<int>(c2)); 846 int actual = wmemcmp(state.ptr1, state.ptr2, (size_t) state.MAX_LEN); 847 848 ASSERT_EQ(signum(expected), signum(actual)); 849 } 850 } 851} 852 853TEST(string, memcpy) { 854 StringTestState<char> state(LARGE); 855 int rand = 4; 856 for (size_t i = 0; i < state.n - 1; i++) { 857 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 858 size_t pos = random() % (state.MAX_LEN - state.len[i]); 859 860 memset(state.ptr1, rand, state.len[i]); 861 memset(state.ptr1 + state.len[i], ~rand, state.MAX_LEN - state.len[i]); 862 863 memset(state.ptr2, rand, state.len[i]); 864 memset(state.ptr2 + state.len[i], ~rand, state.MAX_LEN - state.len[i]); 865 memset(state.ptr2 + pos, '\0', state.len[i]); 866 867 ASSERT_FALSE(memcpy(state.ptr2 + pos, state.ptr1 + pos, state.len[i]) != state.ptr2 + pos); 868 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN)); 869 } 870 } 871} 872 873TEST(string, memset) { 874 StringTestState<char> state(LARGE); 875 char ch = 'P'; 876 for (size_t i = 0; i < state.n - 1; i++) { 877 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 878 memset(state.ptr1, ~ch, state.MAX_LEN); 879 memcpy(state.ptr2, state.ptr1, state.MAX_LEN); 880 881 size_t pos = random () % (state.MAX_LEN - state.len[i]); 882 for (size_t k = pos; k < pos + state.len[i]; k++) { 883 state.ptr1[k] = ch; 884 } 885 886 ASSERT_TRUE(memset(state.ptr2 + pos, ch, state.len[i]) == state.ptr2 + pos); 887 888 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN)); 889 } 890 } 891} 892 893TEST(string, memmove) { 894 StringTestState<char> state(LARGE); 895 for (size_t i = 0; i < state.n - 1; i++) { 896 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 897 memset(state.ptr1, 'Q', 2 * state.MAX_LEN); 898 899 size_t pos = random() % (state.MAX_LEN - state.len[i]); 900 901 memset(state.ptr1, 'R', state.len[i]); 902 memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN); 903 memcpy(state.ptr, state.ptr1, state.len[i]); 904 memcpy(state.ptr1 + pos, state.ptr, state.len[i]); 905 906 ASSERT_TRUE(memmove(state.ptr2 + pos, state.ptr2, state.len[i]) == state.ptr2 + pos); 907 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr1, 2 * state.MAX_LEN)); 908 } 909 } 910} 911 912TEST(string, memmove_cache_size) { 913 size_t len = 600000; 914 int max_alignment = 31; 915 int alignments[] = {0, 5, 11, 29, 30}; 916 char* ptr = reinterpret_cast<char*>(malloc(sizeof(char) * len)); 917 char* ptr1 = reinterpret_cast<char*>(malloc(2 * sizeof(char) * len)); 918 char* glob_ptr2 = reinterpret_cast<char*>(malloc(2 * sizeof(char) * len + max_alignment)); 919 size_t pos = 64; 920 921 ASSERT_TRUE(ptr != NULL); 922 ASSERT_TRUE(ptr1 != NULL); 923 ASSERT_TRUE(glob_ptr2 != NULL); 924 925 for (int i = 0; i < 5; i++) { 926 char* ptr2 = glob_ptr2 + alignments[i]; 927 memset(ptr1, 'S', 2 * len); 928 memset(ptr1, 'T', len); 929 memcpy(ptr2, ptr1, 2 * len); 930 memcpy(ptr, ptr1, len); 931 memcpy(ptr1 + pos, ptr, len); 932 933 ASSERT_TRUE(memmove(ptr2 + pos, ptr, len) == ptr2 + pos); 934 ASSERT_EQ(0, memcmp(ptr2, ptr1, 2 * len)); 935 } 936 free(ptr); 937 free(ptr1); 938 free(glob_ptr2); 939} 940 941static void verify_memmove(char* src_copy, char* dst, char* src, size_t size) { 942 memset(dst, 0, size); 943 memcpy(src, src_copy, size); 944 ASSERT_EQ(dst, memmove(dst, src, size)); 945 ASSERT_EQ(0, memcmp(dst, src_copy, size)); 946} 947 948#define MEMMOVE_DATA_SIZE (1024*1024*3) 949 950TEST(string, memmove_check) { 951 char* buffer = reinterpret_cast<char*>(malloc(MEMMOVE_DATA_SIZE)); 952 ASSERT_TRUE(buffer != NULL); 953 954 char* src_data = reinterpret_cast<char*>(malloc(MEMMOVE_DATA_SIZE)); 955 ASSERT_TRUE(src_data != NULL); 956 // Initialize to a known pattern to copy into src for each test and 957 // to compare dst against. 958 for (size_t i = 0; i < MEMMOVE_DATA_SIZE; i++) { 959 src_data[i] = (i + 1) % 255; 960 } 961 962 // Check all different dst offsets between 0 and 127 inclusive. 963 char* src = buffer; 964 for (size_t i = 0; i < 127; i++) { 965 char* dst = buffer + 256 + i; 966 // Small copy. 967 verify_memmove(src_data, dst, src, 1024); 968 969 // Medium copy. 970 verify_memmove(src_data, dst, src, 64 * 1024); 971 972 // Medium copy. 973 verify_memmove(src_data, dst, src, 1024 * 1024 + 128 * 1024); 974 } 975 976 // Check all leftover size offsets between 1 and 127 inclusive. 977 char* dst = buffer + 256; 978 src = buffer; 979 for (size_t size = 1; size < 127; size++) { 980 // Small copy. 981 verify_memmove(src_data, dst, src, 1024); 982 983 // Medium copy. 984 verify_memmove(src_data, dst, src, 64 * 1024); 985 986 // Large copy. 987 verify_memmove(src_data, dst, src, 1024 * 1024 + 128 * 1024); 988 } 989} 990 991TEST(string, bcopy) { 992 StringTestState<char> state(LARGE); 993 for (size_t i = 0; i < state.n; i++) { 994 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 995 memset(state.ptr1, '4', state.MAX_LEN); 996 memset(state.ptr1 + state.MAX_LEN, 'a', state.MAX_LEN); 997 memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN); 998 999 size_t start = random() % (2 * state.MAX_LEN - state.len[i]); 1000 memcpy(state.ptr2 + start, state.ptr1, state.len[i]); 1001 1002 bcopy(state.ptr1, state.ptr1 + start, state.len[i]); 1003 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, 2 * state.MAX_LEN)); 1004 } 1005 } 1006} 1007 1008TEST(string, bzero) { 1009 StringTestState<char> state(LARGE); 1010 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) { 1011 memset(state.ptr1, 'R', state.MAX_LEN); 1012 1013 size_t start = random() % state.MAX_LEN; 1014 size_t end = start + random() % (state.MAX_LEN - start); 1015 1016 memcpy(state.ptr2, state.ptr1, start); 1017 memset(state.ptr2 + start, '\0', end - start); 1018 memcpy(state.ptr2 + end, state.ptr1 + end, state.MAX_LEN - end); 1019 1020 bzero(state.ptr1 + start, end - start); 1021 1022 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN)); 1023 } 1024} 1025 1026static void DoMemcpyTest(uint8_t* src, uint8_t* dst, size_t len) { 1027 memset(src, (len % 255) + 1, len); 1028 memset(dst, 0, len); 1029 1030 ASSERT_EQ(dst, memcpy(dst, src, len)); 1031 ASSERT_TRUE(memcmp(src, dst, len) == 0); 1032} 1033 1034TEST(string, memcpy_align) { 1035 RunSrcDstBufferAlignTest(LARGE, DoMemcpyTest); 1036} 1037 1038TEST(string, memcpy_overread) { 1039 RunSrcDstBufferOverreadTest(DoMemcpyTest); 1040} 1041 1042static void DoMemmoveTest(uint8_t* src, uint8_t* dst, size_t len) { 1043 memset(src, (len % 255) + 1, len); 1044 memset(dst, 0, len); 1045 1046 ASSERT_EQ(dst, memmove(dst, src, len)); 1047 ASSERT_TRUE(memcmp(src, dst, len) == 0); 1048} 1049 1050TEST(string, memmove_align) { 1051 RunSrcDstBufferAlignTest(LARGE, DoMemmoveTest); 1052} 1053 1054TEST(string, memmove_overread) { 1055 RunSrcDstBufferOverreadTest(DoMemmoveTest); 1056} 1057 1058static void DoMemsetTest(uint8_t* buf, size_t len) { 1059 for (size_t i = 0; i < len; i++) { 1060 buf[i] = 0; 1061 } 1062 int value = (len % 255) + 1; 1063 ASSERT_EQ(buf, memset(buf, value, len)); 1064 for (size_t i = 0; i < len; i++) { 1065 ASSERT_EQ(value, buf[i]); 1066 } 1067} 1068 1069TEST(string, memset_align) { 1070 RunSingleBufferAlignTest(LARGE, DoMemsetTest); 1071} 1072 1073static void DoStrlenTest(uint8_t* buf, size_t len) { 1074 if (len >= 1) { 1075 memset(buf, (32 + (len % 96)), len - 1); 1076 buf[len-1] = '\0'; 1077 ASSERT_EQ(len-1, strlen(reinterpret_cast<char*>(buf))); 1078 } 1079} 1080 1081TEST(string, strlen_align) { 1082 RunSingleBufferAlignTest(LARGE, DoStrlenTest); 1083} 1084 1085TEST(string, strlen_overread) { 1086 RunSingleBufferOverreadTest(DoStrlenTest); 1087} 1088 1089static void DoStrcpyTest(uint8_t* src, uint8_t* dst, size_t len) { 1090 if (len >= 1) { 1091 memset(src, (32 + (len % 96)), len - 1); 1092 src[len-1] = '\0'; 1093 memset(dst, 0, len); 1094 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcpy(reinterpret_cast<char*>(dst), 1095 reinterpret_cast<char*>(src)))); 1096 ASSERT_TRUE(memcmp(src, dst, len) == 0); 1097 } 1098} 1099 1100TEST(string, strcpy_align) { 1101 RunSrcDstBufferAlignTest(LARGE, DoStrcpyTest); 1102} 1103 1104TEST(string, strcpy_overread) { 1105 RunSrcDstBufferOverreadTest(DoStrcpyTest); 1106} 1107 1108#if defined(STRLCPY_SUPPORTED) 1109static void DoStrlcpyTest(uint8_t* src, uint8_t* dst, size_t len) { 1110 if (len >= 1) { 1111 memset(src, (32 + (len % 96)), len - 1); 1112 src[len-1] = '\0'; 1113 memset(dst, 0, len); 1114 ASSERT_EQ(len-1, strlcpy(reinterpret_cast<char*>(dst), 1115 reinterpret_cast<char*>(src), len)); 1116 ASSERT_TRUE(memcmp(src, dst, len) == 0); 1117 } 1118} 1119#endif 1120 1121TEST(string, strlcpy_align) { 1122#if defined(STRLCPY_SUPPORTED) 1123 RunSrcDstBufferAlignTest(LARGE, DoStrlcpyTest); 1124#else 1125 GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform."; 1126#endif 1127} 1128 1129TEST(string, strlcpy_overread) { 1130#if defined(STRLCPY_SUPPORTED) 1131 RunSrcDstBufferOverreadTest(DoStrlcpyTest); 1132#else 1133 GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform."; 1134#endif 1135} 1136 1137 1138static void DoStpcpyTest(uint8_t* src, uint8_t* dst, size_t len) { 1139 if (len >= 1) { 1140 memset(src, (32 + (len % 96)), len - 1); 1141 src[len-1] = '\0'; 1142 memset(dst, 0, len); 1143 ASSERT_EQ(dst+len-1, reinterpret_cast<uint8_t*>(stpcpy(reinterpret_cast<char*>(dst), 1144 reinterpret_cast<char*>(src)))); 1145 ASSERT_TRUE(memcmp(src, dst, len) == 0); 1146 } 1147} 1148 1149TEST(string, stpcpy_align) { 1150 RunSrcDstBufferAlignTest(LARGE, DoStpcpyTest); 1151} 1152 1153TEST(string, stpcpy_overread) { 1154 RunSrcDstBufferOverreadTest(DoStpcpyTest); 1155} 1156 1157// Use our own incrementer to cut down on the total number of calls. 1158static size_t LargeSetIncrement(size_t len) { 1159 if (len >= 4096) { 1160 return 4096; 1161 } else if (len >= 1024) { 1162 return 1024; 1163 } else if (len >= 256) { 1164 return 256; 1165 } 1166 return 1; 1167} 1168 1169#define STRCAT_DST_LEN 128 1170 1171static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) { 1172 if (len >= 1) { 1173 int value = 32 + (len % 96); 1174 memset(src, value, len - 1); 1175 src[len-1] = '\0'; 1176 1177 if (len >= STRCAT_DST_LEN) { 1178 // Create a small buffer for doing quick compares in each loop. 1179 uint8_t cmp_buf[STRCAT_DST_LEN]; 1180 // Make sure dst string contains a different value then the src string. 1181 int value2 = 32 + (value + 2) % 96; 1182 memset(cmp_buf, value2, sizeof(cmp_buf)); 1183 1184 for (size_t i = 1; i <= STRCAT_DST_LEN; i++) { 1185 memset(dst, value2, i-1); 1186 memset(dst+i-1, 0, len-i); 1187 src[len-i] = '\0'; 1188 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst), 1189 reinterpret_cast<char*>(src)))); 1190 ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0); 1191 ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0); 1192 } 1193 } else { 1194 dst[0] = '\0'; 1195 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst), 1196 reinterpret_cast<char*>(src)))); 1197 ASSERT_TRUE(memcmp(src, dst, len) == 0); 1198 } 1199 } 1200} 1201 1202TEST(string, strcat_align) { 1203 RunSrcDstBufferAlignTest(MEDIUM, DoStrcatTest, LargeSetIncrement); 1204} 1205 1206TEST(string, strcat_overread) { 1207 RunSrcDstBufferOverreadTest(DoStrcatTest); 1208} 1209 1210#if defined(STRLCAT_SUPPORTED) 1211static void DoStrlcatTest(uint8_t* src, uint8_t* dst, size_t len) { 1212 if (len >= 1) { 1213 int value = 32 + (len % 96); 1214 memset(src, value, len - 1); 1215 src[len-1] = '\0'; 1216 1217 if (len >= STRCAT_DST_LEN) { 1218 // Create a small buffer for doing quick compares in each loop. 1219 uint8_t cmp_buf[STRCAT_DST_LEN]; 1220 // Make sure dst string contains a different value then the src string. 1221 int value2 = 32 + (value + 2) % 96; 1222 memset(cmp_buf, value2, sizeof(cmp_buf)); 1223 1224 for (size_t i = 1; i <= STRCAT_DST_LEN; i++) { 1225 memset(dst, value2, i-1); 1226 memset(dst+i-1, 0, len-i); 1227 src[len-i] = '\0'; 1228 ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst), 1229 reinterpret_cast<char*>(src), len)); 1230 ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0); 1231 ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0); 1232 } 1233 } else { 1234 dst[0] = '\0'; 1235 ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst), 1236 reinterpret_cast<char*>(src), len)); 1237 ASSERT_TRUE(memcmp(src, dst, len) == 0); 1238 } 1239 } 1240} 1241#endif 1242 1243TEST(string, strlcat_align) { 1244#if defined(STRLCAT_SUPPORTED) 1245 RunSrcDstBufferAlignTest(MEDIUM, DoStrlcatTest, LargeSetIncrement); 1246#else 1247 GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform."; 1248#endif 1249} 1250 1251TEST(string, strlcat_overread) { 1252#if defined(STRLCAT_SUPPORTED) 1253 RunSrcDstBufferOverreadTest(DoStrlcatTest); 1254#else 1255 GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform."; 1256#endif 1257} 1258 1259static void DoStrcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) { 1260 if (len >= 1) { 1261 memset(buf1, (32 + (len % 96)), len - 1); 1262 buf1[len-1] = '\0'; 1263 memset(buf2, (32 + (len % 96)), len - 1); 1264 buf2[len-1] = '\0'; 1265 ASSERT_EQ(0, strcmp(reinterpret_cast<char*>(buf1), 1266 reinterpret_cast<char*>(buf2))); 1267 } 1268} 1269 1270static void DoStrcmpFailTest(uint8_t* buf1, uint8_t* buf2, size_t len1, size_t len2) { 1271 // Do string length differences. 1272 int c = (32 + (len1 % 96)); 1273 memset(buf1, c, len1 - 1); 1274 buf1[len1-1] = '\0'; 1275 memset(buf2, c, len2 - 1); 1276 buf2[len2-1] = '\0'; 1277 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1), 1278 reinterpret_cast<char*>(buf2))); 1279 1280 // Do single character differences. 1281 size_t len; 1282 if (len1 > len2) { 1283 len = len2; 1284 } else { 1285 len = len1; 1286 } 1287 // Need at least a two character buffer to do this test. 1288 if (len > 1) { 1289 buf1[len-1] = '\0'; 1290 buf2[len-1] = '\0'; 1291 int diff_c = (c + 1) % 96; 1292 1293 buf1[len-2] = diff_c; 1294 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1), 1295 reinterpret_cast<char*>(buf2))); 1296 1297 buf1[len-2] = c; 1298 buf2[len-2] = diff_c; 1299 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1), 1300 reinterpret_cast<char*>(buf2))); 1301 } 1302} 1303 1304TEST(string, strcmp_align) { 1305 RunCmpBufferAlignTest(MEDIUM, DoStrcmpTest, DoStrcmpFailTest, LargeSetIncrement); 1306} 1307 1308TEST(string, strcmp_overread) { 1309 RunCmpBufferOverreadTest(DoStrcmpTest, DoStrcmpFailTest); 1310} 1311 1312static void DoMemcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) { 1313 memset(buf1, len+1, len); 1314 memset(buf2, len+1, len); 1315 ASSERT_EQ(0, memcmp(buf1, buf2, len)); 1316} 1317 1318static void DoMemcmpFailTest(uint8_t* buf1, uint8_t* buf2, size_t len1, size_t len2) { 1319 size_t len; 1320 if (len1 > len2) { 1321 len = len2; 1322 } else { 1323 len = len1; 1324 } 1325 1326 memset(buf1, len2+1, len); 1327 buf1[len-1] = len2; 1328 memset(buf2, len2+1, len); 1329 ASSERT_NE(0, memcmp(buf1, buf2, len)); 1330 1331 buf1[len-1] = len2+1; 1332 buf2[len-1] = len2; 1333 ASSERT_NE(0, memcmp(buf1, buf2, len)); 1334} 1335 1336TEST(string, memcmp_align) { 1337 RunCmpBufferAlignTest(MEDIUM, DoMemcmpTest, DoMemcmpFailTest, LargeSetIncrement); 1338} 1339 1340TEST(string, memcmp_overread) { 1341 RunCmpBufferOverreadTest(DoMemcmpTest, DoMemcmpFailTest); 1342} 1343 1344static void DoStrchrTest(uint8_t* buf, size_t len) { 1345 if (len >= 1) { 1346 char value = 32 + (len % 96); 1347 char search_value = 33 + (len % 96); 1348 memset(buf, value, len - 1); 1349 buf[len-1] = '\0'; 1350 ASSERT_EQ(NULL, strchr(reinterpret_cast<char*>(buf), search_value)); 1351 ASSERT_EQ(reinterpret_cast<char*>(&buf[len-1]), strchr(reinterpret_cast<char*>(buf), '\0')); 1352 if (len >= 2) { 1353 buf[0] = search_value; 1354 ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strchr(reinterpret_cast<char*>(buf), search_value)); 1355 buf[0] = value; 1356 buf[len-2] = search_value; 1357 ASSERT_EQ(reinterpret_cast<char*>(&buf[len-2]), strchr(reinterpret_cast<char*>(buf), search_value)); 1358 } 1359 } 1360} 1361 1362TEST(string, strchr_align) { 1363 RunSingleBufferAlignTest(MEDIUM, DoStrchrTest); 1364} 1365 1366TEST(string, strchr_overread) { 1367 RunSingleBufferOverreadTest(DoStrchrTest); 1368} 1369 1370static void TestBasename(const char* in, const char* expected_out) { 1371 errno = 0; 1372 const char* out = basename(in); 1373 ASSERT_STREQ(expected_out, out) << in; 1374 ASSERT_EQ(0, errno) << in; 1375} 1376 1377TEST(string, __gnu_basename) { 1378 TestBasename("", ""); 1379 TestBasename("/usr/lib", "lib"); 1380 TestBasename("/usr/", ""); 1381 TestBasename("usr", "usr"); 1382 TestBasename("/", ""); 1383 TestBasename(".", "."); 1384 TestBasename("..", ".."); 1385 TestBasename("///", ""); 1386 TestBasename("//usr//lib//", ""); 1387} 1388