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