• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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