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