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