blob: 96b4143971188a0a262ff58f6adbe00d2f2e4ea5 [file] [log] [blame]
Irina Tirdeab5f053b2012-09-08 09:17:54 +03001/*
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
Elliott Hughes416d7dd2014-08-18 17:28:32 -070017#define _GNU_SOURCE 1
18
Elliott Hughes09c39d62014-08-19 14:30:30 -070019#include <string.h>
Irina Tirdeab5f053b2012-09-08 09:17:54 +030020
21#include <errno.h>
Elliott Hughes09c39d62014-08-19 14:30:30 -070022#include <gtest/gtest.h>
Dan Alberte5fdaa42014-06-14 01:04:31 +000023#include <malloc.h>
Anna Tikhonova036154b2012-10-05 15:21:11 +040024#include <math.h>
Elliott Hughesd2a9fb32015-07-27 20:55:03 -070025#include <stdint.h>
Irina Tirdeab5f053b2012-09-08 09:17:54 +030026
Christopher Ferrisb687ad32013-11-06 17:32:11 -080027#include "buffer_tests.h"
28
Christopher Ferris13f26a72016-01-13 13:47:58 -080029#if defined(NOFORTIFY)
30#define STRING_TEST string_nofortify
31#else
32#define STRING_TEST string
33#endif
34
Christopher Ferris14687652014-11-10 13:58:17 -080035#if defined(__BIONIC__)
36#define STRLCPY_SUPPORTED
37#define STRLCAT_SUPPORTED
38#endif
39
Anna Tikhonova036154b2012-10-05 15:21:11 +040040#define KB 1024
41#define SMALL 1*KB
Christopher Ferrisb687ad32013-11-06 17:32:11 -080042#define MEDIUM 4*KB
Anna Tikhonova036154b2012-10-05 15:21:11 +040043#define LARGE 64*KB
44
45static int signum(int i) {
46 if (i < 0) {
47 return -1;
48 } else if (i > 0) {
49 return 1;
50 }
51 return 0;
52}
53
Christopher Ferris13f26a72016-01-13 13:47:58 -080054TEST(STRING_TEST, strerror) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +030055 // Valid.
56 ASSERT_STREQ("Success", strerror(0));
57 ASSERT_STREQ("Operation not permitted", strerror(1));
58
59 // Invalid.
Elliott Hughese6e60062013-01-10 16:01:59 -080060 ASSERT_STREQ("Unknown error -1", strerror(-1));
Irina Tirdeab5f053b2012-09-08 09:17:54 +030061 ASSERT_STREQ("Unknown error 1234", strerror(1234));
62}
63
Christopher Ferrisf04935c2013-12-20 18:43:21 -080064#if defined(__BIONIC__)
Elliott Hughesad88a082012-10-24 18:37:21 -070065static void* ConcurrentStrErrorFn(void*) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +030066 bool equal = (strcmp("Unknown error 2002", strerror(2002)) == 0);
67 return reinterpret_cast<void*>(equal);
68}
Christopher Ferrisf04935c2013-12-20 18:43:21 -080069#endif // __BIONIC__
Irina Tirdeab5f053b2012-09-08 09:17:54 +030070
Christopher Ferrisf04935c2013-12-20 18:43:21 -080071// glibc's strerror isn't thread safe, only its strsignal.
Christopher Ferris13f26a72016-01-13 13:47:58 -080072TEST(STRING_TEST, strerror_concurrent) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -080073#if defined(__BIONIC__)
Irina Tirdeab5f053b2012-09-08 09:17:54 +030074 const char* strerror1001 = strerror(1001);
75 ASSERT_STREQ("Unknown error 1001", strerror1001);
76
77 pthread_t t;
78 ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrErrorFn, NULL));
79 void* result;
80 ASSERT_EQ(0, pthread_join(t, &result));
81 ASSERT_TRUE(static_cast<bool>(result));
82
83 ASSERT_STREQ("Unknown error 1001", strerror1001);
Christopher Ferrisf04935c2013-12-20 18:43:21 -080084#else // __BIONIC__
Christopher Ferris14687652014-11-10 13:58:17 -080085 GTEST_LOG_(INFO) << "Skipping test, requires a thread safe strerror.";
Christopher Ferrisf04935c2013-12-20 18:43:21 -080086#endif // __BIONIC__
Irina Tirdeab5f053b2012-09-08 09:17:54 +030087}
Elliott Hughesad88a082012-10-24 18:37:21 -070088
Christopher Ferris13f26a72016-01-13 13:47:58 -080089TEST(STRING_TEST, gnu_strerror_r) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +030090 char buf[256];
91
Elliott Hughes416d7dd2014-08-18 17:28:32 -070092 // Note that glibc doesn't necessarily write into the buffer.
93
Irina Tirdeab5f053b2012-09-08 09:17:54 +030094 // Valid.
Elliott Hughes416d7dd2014-08-18 17:28:32 -070095 ASSERT_STREQ("Success", strerror_r(0, buf, sizeof(buf)));
96#if defined(__BIONIC__)
Irina Tirdeab5f053b2012-09-08 09:17:54 +030097 ASSERT_STREQ("Success", buf);
Elliott Hughes416d7dd2014-08-18 17:28:32 -070098#endif
99 ASSERT_STREQ("Operation not permitted", strerror_r(1, buf, sizeof(buf)));
100#if defined(__BIONIC__)
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300101 ASSERT_STREQ("Operation not permitted", buf);
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700102#endif
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300103
104 // Invalid.
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700105 ASSERT_STREQ("Unknown error -1", strerror_r(-1, buf, sizeof(buf)));
Nick Kralevich60605892013-01-15 10:35:09 -0800106 ASSERT_STREQ("Unknown error -1", buf);
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700107 ASSERT_STREQ("Unknown error 1234", strerror_r(1234, buf, sizeof(buf)));
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300108 ASSERT_STREQ("Unknown error 1234", buf);
109
110 // Buffer too small.
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700111 errno = 0;
112 memset(buf, 0, sizeof(buf));
113 ASSERT_EQ(buf, strerror_r(4567, buf, 2));
114 ASSERT_STREQ("U", buf);
115 // The GNU strerror_r doesn't set errno (the POSIX one sets it to ERANGE).
116 ASSERT_EQ(0, errno);
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300117}
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300118
Christopher Ferris13f26a72016-01-13 13:47:58 -0800119TEST(STRING_TEST, strsignal) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300120 // A regular signal.
121 ASSERT_STREQ("Hangup", strsignal(1));
122
123 // A real-time signal.
Elliott Hughes0990d4f2014-04-30 09:45:40 -0700124 ASSERT_STREQ("Real-time signal 14", strsignal(SIGRTMIN + 14));
125 // One of the signals the C library keeps to itself.
126 ASSERT_STREQ("Unknown signal 32", strsignal(__SIGRTMIN));
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300127
128 // Errors.
129 ASSERT_STREQ("Unknown signal -1", strsignal(-1)); // Too small.
130 ASSERT_STREQ("Unknown signal 0", strsignal(0)); // Still too small.
131 ASSERT_STREQ("Unknown signal 1234", strsignal(1234)); // Too large.
132}
133
Elliott Hughesad88a082012-10-24 18:37:21 -0700134static void* ConcurrentStrSignalFn(void*) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300135 bool equal = (strcmp("Unknown signal 2002", strsignal(2002)) == 0);
136 return reinterpret_cast<void*>(equal);
137}
138
Christopher Ferris13f26a72016-01-13 13:47:58 -0800139TEST(STRING_TEST, strsignal_concurrent) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300140 const char* strsignal1001 = strsignal(1001);
141 ASSERT_STREQ("Unknown signal 1001", strsignal1001);
142
143 pthread_t t;
144 ASSERT_EQ(0, pthread_create(&t, NULL, ConcurrentStrSignalFn, NULL));
145 void* result;
146 ASSERT_EQ(0, pthread_join(t, &result));
147 ASSERT_TRUE(static_cast<bool>(result));
148
149 ASSERT_STREQ("Unknown signal 1001", strsignal1001);
150}
Anna Tikhonova036154b2012-10-05 15:21:11 +0400151
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700152// TODO: where did this number come from?
Anna Tikhonova036154b2012-10-05 15:21:11 +0400153#define ITER 500
154
155// For every length we want to test, vary and change alignment
156// of allocated memory, fill it with some values, calculate
157// expected result and then run function and compare what we got.
158// These tests contributed by Intel Corporation.
159// TODO: make these tests more intention-revealing and less random.
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400160template<class Character>
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700161class StringTestState {
162 public:
163 StringTestState(size_t MAX_LEN) : MAX_LEN(MAX_LEN), align1_index_(0), align2_index_(0) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400164 int max_alignment = 64;
165
166 // TODO: fix the tests to not sometimes use twice their specified "MAX_LEN".
Dan Alberte5fdaa42014-06-14 01:04:31 +0000167 glob_ptr = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
168 glob_ptr1 = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
169 glob_ptr2 = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400170
171 InitLenArray();
172
173 srandom(1234);
174 }
175
176 ~StringTestState() {
177 free(glob_ptr);
178 free(glob_ptr1);
179 free(glob_ptr2);
180 }
181
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700182 void BeginIterations() {
183 align1_index_ = 0;
184 align2_index_ = 0;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400185
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700186 ResetPointers();
187 }
188
189 bool HasNextIteration() {
190 return (align1_index_ != (alignments_size - 1) || align2_index_ != (alignments_size - 1));
191 }
192
193 void NextIteration() {
194 if (align1_index_ == (alignments_size - 1) && align2_index_ == (alignments_size - 1)) {
195 return;
196 }
197
198 if (align1_index_ == (alignments_size - 1)) {
199 align1_index_ = 0;
200 align2_index_++;
201 } else {
202 align1_index_++;
203 }
204
205 ResetPointers();
Anna Tikhonova036154b2012-10-05 15:21:11 +0400206 }
207
208 const size_t MAX_LEN;
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400209 Character *ptr, *ptr1, *ptr2;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400210 size_t n;
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700211 size_t len[ITER + 1];
Anna Tikhonova036154b2012-10-05 15:21:11 +0400212
213 private:
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700214 static size_t alignments[];
215 static size_t alignments_size;
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400216 Character *glob_ptr, *glob_ptr1, *glob_ptr2;
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700217 size_t align1_index_, align2_index_;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400218
219 // Calculate input lengths and fill state.len with them.
220 // Test small lengths with more density than big ones. Manually push
221 // smallest (0) and biggest (MAX_LEN) lengths. Avoid repeats.
222 // Return number of lengths to test.
223 void InitLenArray() {
224 n = 0;
225 len[n++] = 0;
226 for (size_t i = 1; i < ITER; ++i) {
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700227 size_t l = static_cast<size_t>(exp(log(static_cast<double>(MAX_LEN)) * i / ITER));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400228 if (l != len[n - 1]) {
229 len[n++] = l;
230 }
231 }
232 len[n++] = MAX_LEN;
233 }
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700234
235 void ResetPointers() {
236 if (align1_index_ == alignments_size || align2_index_ == alignments_size) {
237 ptr = ptr1 = ptr2 = nullptr;
238 } else {
239 ptr = glob_ptr + alignments[align1_index_];
240 ptr1 = glob_ptr1 + alignments[align1_index_];
241 ptr2 = glob_ptr2 + alignments[align2_index_];
242 }
243 }
Anna Tikhonova036154b2012-10-05 15:21:11 +0400244};
245
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700246template<class Character>
247size_t StringTestState<Character>::alignments[] = { 24, 32, 16, 48, 0, 1, 2, 3, 4, 5, 6, 7, 11 };
248
249template<class Character>
250size_t StringTestState<Character>::alignments_size = sizeof(alignments)/sizeof(size_t);
251
Christopher Ferris13f26a72016-01-13 13:47:58 -0800252TEST(STRING_TEST, strcat) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400253 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400254 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700255 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400256 memset(state.ptr2, '\2', state.MAX_LEN);
257 state.ptr2[state.MAX_LEN - 1] = '\0';
258 memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
259
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700260 memset(state.ptr1, 'L', state.len[i]);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400261 state.ptr1[random() % state.len[i]] = '\0';
262 state.ptr1[state.len[i] - 1] = '\0';
263
264 strcpy(state.ptr + state.MAX_LEN - 1, state.ptr1);
265
266 EXPECT_TRUE(strcat(state.ptr2, state.ptr1) == state.ptr2);
267 EXPECT_TRUE(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN) == 0);
268 }
269 }
270}
271
Nick Kralevich13476de2013-06-03 10:58:06 -0700272// one byte target with "\0" source
Christopher Ferris13f26a72016-01-13 13:47:58 -0800273TEST(STRING_TEST, strcpy2) {
Nick Kralevich13476de2013-06-03 10:58:06 -0700274 char buf[1];
275 char* orig = strdup("");
Christopher Ferris950a58e2014-04-04 14:38:18 -0700276 ASSERT_EQ(buf, strcpy(buf, orig));
Nick Kralevich13476de2013-06-03 10:58:06 -0700277 ASSERT_EQ('\0', buf[0]);
278 free(orig);
279}
280
281// multibyte target where we under fill target
Christopher Ferris13f26a72016-01-13 13:47:58 -0800282TEST(STRING_TEST, strcpy3) {
Nick Kralevich13476de2013-06-03 10:58:06 -0700283 char buf[10];
284 char* orig = strdup("12345");
285 memset(buf, 'A', sizeof(buf));
Christopher Ferris950a58e2014-04-04 14:38:18 -0700286 ASSERT_EQ(buf, strcpy(buf, orig));
287 ASSERT_STREQ("12345", buf);
Nick Kralevich13476de2013-06-03 10:58:06 -0700288 ASSERT_EQ('A', buf[6]);
289 ASSERT_EQ('A', buf[7]);
290 ASSERT_EQ('A', buf[8]);
291 ASSERT_EQ('A', buf[9]);
292 free(orig);
293}
294
295// multibyte target where we fill target exactly
Christopher Ferris13f26a72016-01-13 13:47:58 -0800296TEST(STRING_TEST, strcpy4) {
Nick Kralevich13476de2013-06-03 10:58:06 -0700297 char buf[10];
298 char* orig = strdup("123456789");
299 memset(buf, 'A', sizeof(buf));
Christopher Ferris950a58e2014-04-04 14:38:18 -0700300 ASSERT_EQ(buf, strcpy(buf, orig));
301 ASSERT_STREQ("123456789", buf);
302 free(orig);
303}
304
305// one byte target with "\0" source
Christopher Ferris13f26a72016-01-13 13:47:58 -0800306TEST(STRING_TEST, stpcpy2) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700307 char buf[1];
308 char* orig = strdup("");
309 ASSERT_EQ(buf, stpcpy(buf, orig));
310 ASSERT_EQ('\0', buf[0]);
311 free(orig);
312}
313
314// multibyte target where we under fill target
Christopher Ferris13f26a72016-01-13 13:47:58 -0800315TEST(STRING_TEST, stpcpy3) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700316 char buf[10];
317 char* orig = strdup("12345");
318 memset(buf, 'A', sizeof(buf));
319 ASSERT_EQ(buf+strlen(orig), stpcpy(buf, orig));
320 ASSERT_STREQ("12345", buf);
321 ASSERT_EQ('A', buf[6]);
322 ASSERT_EQ('A', buf[7]);
323 ASSERT_EQ('A', buf[8]);
324 ASSERT_EQ('A', buf[9]);
325 free(orig);
326}
327
328// multibyte target where we fill target exactly
Christopher Ferris13f26a72016-01-13 13:47:58 -0800329TEST(STRING_TEST, stpcpy4) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700330 char buf[10];
331 char* orig = strdup("123456789");
332 memset(buf, 'A', sizeof(buf));
333 ASSERT_EQ(buf+strlen(orig), stpcpy(buf, orig));
334 ASSERT_STREQ("123456789", buf);
Nick Kralevich13476de2013-06-03 10:58:06 -0700335 free(orig);
336}
337
Christopher Ferris13f26a72016-01-13 13:47:58 -0800338TEST(STRING_TEST, strcat2) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700339 char buf[10];
340 memset(buf, 'A', sizeof(buf));
341 buf[0] = 'a';
342 buf[1] = '\0';
343 char* res = strcat(buf, "01234");
344 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700345 ASSERT_STREQ("a01234", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700346 ASSERT_EQ('A', buf[7]);
347 ASSERT_EQ('A', buf[8]);
348 ASSERT_EQ('A', buf[9]);
349}
350
Christopher Ferris13f26a72016-01-13 13:47:58 -0800351TEST(STRING_TEST, strcat3) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700352 char buf[10];
353 memset(buf, 'A', sizeof(buf));
354 buf[0] = 'a';
355 buf[1] = '\0';
356 char* res = strcat(buf, "01234567");
357 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700358 ASSERT_STREQ("a01234567", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700359}
360
Christopher Ferris13f26a72016-01-13 13:47:58 -0800361TEST(STRING_TEST, strncat2) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700362 char buf[10];
363 memset(buf, 'A', sizeof(buf));
364 buf[0] = 'a';
365 buf[1] = '\0';
366 char* res = strncat(buf, "01234", sizeof(buf) - strlen(buf) - 1);
367 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700368 ASSERT_STREQ("a01234", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700369 ASSERT_EQ('A', buf[7]);
370 ASSERT_EQ('A', buf[8]);
371 ASSERT_EQ('A', buf[9]);
372}
373
Christopher Ferris13f26a72016-01-13 13:47:58 -0800374TEST(STRING_TEST, strncat3) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700375 char buf[10];
376 memset(buf, 'A', sizeof(buf));
377 buf[0] = 'a';
378 buf[1] = '\0';
379 char* res = strncat(buf, "0123456789", 5);
380 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700381 ASSERT_STREQ("a01234", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700382 ASSERT_EQ('A', buf[7]);
383 ASSERT_EQ('A', buf[8]);
384 ASSERT_EQ('A', buf[9]);
385}
386
Christopher Ferris13f26a72016-01-13 13:47:58 -0800387TEST(STRING_TEST, strncat4) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700388 char buf[10];
389 memset(buf, 'A', sizeof(buf));
390 buf[0] = 'a';
391 buf[1] = '\0';
392 char* res = strncat(buf, "01234567", 8);
393 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700394 ASSERT_STREQ("a01234567", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700395}
396
Christopher Ferris13f26a72016-01-13 13:47:58 -0800397TEST(STRING_TEST, strncat5) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700398 char buf[10];
399 memset(buf, 'A', sizeof(buf));
400 buf[0] = 'a';
401 buf[1] = '\0';
402 char* res = strncat(buf, "01234567", 9);
403 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700404 ASSERT_STREQ("a01234567", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700405}
406
Christopher Ferris13f26a72016-01-13 13:47:58 -0800407TEST(STRING_TEST, strchr_with_0) {
Nick Kralevich4f40e512013-04-19 16:54:22 -0700408 char buf[10];
409 const char* s = "01234";
410 memcpy(buf, s, strlen(s) + 1);
411 EXPECT_TRUE(strchr(buf, '\0') == (buf + strlen(s)));
412}
413
Christopher Ferris13f26a72016-01-13 13:47:58 -0800414TEST(STRING_TEST, strchr_multiple) {
Christopher Ferris3a657d02014-06-27 12:33:22 -0700415 char str[128];
416 memset(str, 'a', sizeof(str) - 1);
417 str[sizeof(str)-1] = '\0';
418
419 // Verify that strchr finds the first occurrence of 'a' in a string
420 // filled with 'a' characters. Iterate over the string putting
421 // non 'a' characters at the front of the string during each iteration
422 // and continue to verify that strchr can find the first occurrence
423 // properly. The idea is to cover all possible alignments of the location
424 // of the first occurrence of the 'a' character and which includes
425 // other 'a' characters close by.
426 for (size_t i = 0; i < sizeof(str) - 1; i++) {
427 EXPECT_EQ(&str[i], strchr(str, 'a'));
428 str[i] = 'b';
429 }
430}
431
Christopher Ferris13f26a72016-01-13 13:47:58 -0800432TEST(STRING_TEST, strchr) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700433 int seek_char = 'R';
Anna Tikhonova036154b2012-10-05 15:21:11 +0400434
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400435 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400436 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700437 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400438 if (~seek_char > 0) {
439 memset(state.ptr1, ~seek_char, state.len[i]);
440 } else {
441 memset(state.ptr1, '\1', state.len[i]);
442 }
443 state.ptr1[state.len[i] - 1] = '\0';
444
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700445 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400446 char* expected;
447 if (pos >= state.len[i] - 1) {
448 if (seek_char == 0) {
449 expected = state.ptr1 + state.len[i] - 1;
450 } else {
451 expected = NULL;
452 }
453 } else {
454 state.ptr1[pos] = seek_char;
455 expected = state.ptr1 + pos;
456 }
457
458 ASSERT_TRUE(strchr(state.ptr1, seek_char) == expected);
459 }
460 }
461}
462
Christopher Ferris13f26a72016-01-13 13:47:58 -0800463TEST(STRING_TEST, strchrnul) {
Elliott Hughes7ac3c122015-08-26 09:59:29 -0700464 const char* s = "01234222";
465 EXPECT_TRUE(strchrnul(s, '2') == &s[2]);
466 EXPECT_TRUE(strchrnul(s, '8') == (s + strlen(s)));
467 EXPECT_TRUE(strchrnul(s, '\0') == (s + strlen(s)));
468}
469
Christopher Ferris13f26a72016-01-13 13:47:58 -0800470TEST(STRING_TEST, strcmp) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400471 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400472 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700473 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400474 memset(state.ptr1, 'v', state.MAX_LEN);
475 memset(state.ptr2, 'n', state.MAX_LEN);
476 state.ptr1[state.len[i] - 1] = '\0';
477 state.ptr2[state.len[i] - 1] = '\0';
478
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700479 size_t pos = 1 + (random() % (state.MAX_LEN - 1));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400480 int actual;
481 int expected;
482 if (pos >= state.len[i] - 1) {
483 memcpy(state.ptr1, state.ptr2, state.len[i]);
484 expected = 0;
485 actual = strcmp(state.ptr1, state.ptr2);
486 } else {
487 memcpy(state.ptr1, state.ptr2, pos);
488 if (state.ptr1[pos] > state.ptr2[pos]) {
489 expected = 1;
490 } else if (state.ptr1[pos] == state.ptr2[pos]) {
491 state.ptr1[pos + 1] = '\0';
492 state.ptr2[pos + 1] = '\0';
493 expected = 0;
494 } else {
495 expected = -1;
496 }
497 actual = strcmp(state.ptr1, state.ptr2);
498 }
499
500 ASSERT_EQ(expected, signum(actual));
501 }
502 }
503}
504
Christopher Ferris13f26a72016-01-13 13:47:58 -0800505TEST(STRING_TEST, stpcpy) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700506 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700507 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700508 size_t pos = random() % state.MAX_LEN;
509
510 memset(state.ptr1, '\2', pos);
511 state.ptr1[pos] = '\0';
512 state.ptr1[state.MAX_LEN - 1] = '\0';
513
514 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
515
516 memset(state.ptr2, '\1', state.MAX_LEN);
517 state.ptr2[state.MAX_LEN - 1] = '\0';
518
519 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
520 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
521 state.ptr[2 * state.MAX_LEN - 1] = '\0';
522
523 ASSERT_TRUE(stpcpy(state.ptr2, state.ptr1) == state.ptr2 + strlen(state.ptr1));
524 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 ||
525 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
526 }
527}
528
Christopher Ferris13f26a72016-01-13 13:47:58 -0800529TEST(STRING_TEST, strcpy) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400530 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700531 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400532 size_t pos = random() % state.MAX_LEN;
533
534 memset(state.ptr1, '\2', pos);
535 state.ptr1[pos] = '\0';
536 state.ptr1[state.MAX_LEN - 1] = '\0';
537
538 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
539
540 memset(state.ptr2, '\1', state.MAX_LEN);
541 state.ptr2[state.MAX_LEN - 1] = '\0';
542
543 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
544 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
545 state.ptr[2 * state.MAX_LEN - 1] = '\0';
546
547 ASSERT_TRUE(strcpy(state.ptr2, state.ptr1) == state.ptr2);
548 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 ||
549 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
550 }
551}
552
Christopher Ferris13f26a72016-01-13 13:47:58 -0800553TEST(STRING_TEST, strlcat) {
Christopher Ferris14687652014-11-10 13:58:17 -0800554#if defined(STRLCAT_SUPPORTED)
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400555 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400556 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700557 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400558 memset(state.ptr2, '\2', state.MAX_LEN + state.len[i]);
559 state.ptr2[state.MAX_LEN - 1] = '\0';
560 memcpy(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]);
561
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700562 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400563 memset(state.ptr1, '\3', pos);
564 state.ptr1[pos] = '\0';
565 if (pos < state.len[i]) {
566 memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, pos + 1);
567 } else {
568 memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, state.len[i]);
569 state.ptr[state.MAX_LEN + state.len[i] - 1] = '\0';
570 }
571
572 strlcat(state.ptr2, state.ptr1, state.MAX_LEN + state.len[i]);
573
574 ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0);
575 }
576 }
Christopher Ferris14687652014-11-10 13:58:17 -0800577#else
578 GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
579#endif
Anna Tikhonova036154b2012-10-05 15:21:11 +0400580}
Anna Tikhonova036154b2012-10-05 15:21:11 +0400581
Christopher Ferris13f26a72016-01-13 13:47:58 -0800582TEST(STRING_TEST, strlcpy) {
Christopher Ferris14687652014-11-10 13:58:17 -0800583#if defined(STRLCPY_SUPPORTED)
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400584 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700585 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
586 int rand = 'O';
Anna Tikhonova036154b2012-10-05 15:21:11 +0400587 memset(state.ptr1, rand, state.MAX_LEN);
588
589 size_t pos = random() % state.MAX_LEN;
590 if (pos < state.MAX_LEN) {
591 state.ptr1[pos] = '\0';
592 }
593 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
594
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700595 memset(state.ptr2, 'I', state.MAX_LEN);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400596 memcpy(state.ptr + state.MAX_LEN, state.ptr2, state.MAX_LEN);
597
598 if (pos > state.MAX_LEN - 1) {
599 memcpy(state.ptr + state.MAX_LEN, state.ptr1, state.MAX_LEN);
600 state.ptr[2 * state.MAX_LEN - 1] = '\0';
601 } else {
602 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
603 }
604
605 ASSERT_EQ(strlcpy(state.ptr2, state.ptr1, state.MAX_LEN), strlen(state.ptr1));
606 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) ||
607 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
608 }
Christopher Ferris14687652014-11-10 13:58:17 -0800609#else
610 GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
611#endif
Anna Tikhonova036154b2012-10-05 15:21:11 +0400612}
Anna Tikhonova036154b2012-10-05 15:21:11 +0400613
Christopher Ferris13f26a72016-01-13 13:47:58 -0800614TEST(STRING_TEST, strncat) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400615 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400616 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700617 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400618 memset(state.ptr2, '\2', state.MAX_LEN);
619 state.ptr2[state.MAX_LEN - 1] = '\0';
620 memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
621
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700622 memset(state.ptr1, 'I', state.len[i]);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400623 state.ptr1[random() % state.len[i]] = '\0';
624 state.ptr1[state.len[i] - 1] = '\0';
625
626 size_t pos = strlen(state.ptr1);
627
628 size_t actual = random() % state.len[i];
629 strncpy(state.ptr + state.MAX_LEN - 1, state.ptr1, std::min(actual, pos));
630 state.ptr[state.MAX_LEN + std::min(actual, pos) - 1] = '\0';
631
632 ASSERT_TRUE(strncat(state.ptr2, state.ptr1, actual) == state.ptr2);
633 ASSERT_EQ(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN), 0);
634 }
635 }
636}
637
Christopher Ferris13f26a72016-01-13 13:47:58 -0800638TEST(STRING_TEST, strncmp) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400639 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400640 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700641 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400642 memset(state.ptr1, 'v', state.MAX_LEN);
643 memset(state.ptr2, 'n', state.MAX_LEN);
644 state.ptr1[state.len[i] - 1] = '\0';
645 state.ptr2[state.len[i] - 1] = '\0';
646
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700647 size_t pos = 1 + (random() % (state.MAX_LEN - 1));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400648 int actual;
649 int expected;
650 if (pos >= state.len[i] - 1) {
651 memcpy(state.ptr1, state.ptr2, state.len[i]);
652 expected = 0;
653 actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
654 } else {
655 memcpy(state.ptr1, state.ptr2, pos);
656 if (state.ptr1[pos] > state.ptr2[pos]) {
657 expected = 1;
658 } else if (state.ptr1[pos] == state.ptr2[pos]) {
659 state.ptr1[pos + 1] = '\0';
660 state.ptr2[pos + 1] = '\0';
661 expected = 0;
662 } else {
663 expected = -1;
664 }
665 actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
666 }
667
668 ASSERT_EQ(expected, signum(actual));
669 }
670 }
671}
672
Christopher Ferris13f26a72016-01-13 13:47:58 -0800673TEST(STRING_TEST, stpncpy) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700674 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700675 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
676 memset(state.ptr1, 'J', state.MAX_LEN);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700677 // Choose a random size for our src buffer.
678 size_t ptr1_len = random() % state.MAX_LEN;
679 state.ptr1[ptr1_len] = '\0';
680 // Copy ptr1 into ptr, used to verify that ptr1 does not get modified.
681 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
682 // Init ptr2 to a set value.
683 memset(state.ptr2, '\1', state.MAX_LEN);
684
685 // Choose a random amount of data to copy.
686 size_t copy_len = random() % state.MAX_LEN;
687
688 // Set the second half of ptr to the expected pattern in ptr2.
689 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
690 memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len);
691 size_t expected_end;
692 if (copy_len > ptr1_len) {
693 memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len);
694 expected_end = ptr1_len;
695 } else {
696 expected_end = copy_len;
697 }
698
699 ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len));
700
701 // Verify ptr1 was not modified.
702 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN));
703 // Verify ptr2 contains the expected data.
704 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN));
705 }
706}
707
Christopher Ferris13f26a72016-01-13 13:47:58 -0800708TEST(STRING_TEST, strncpy) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400709 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700710 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700711 // Choose a random value to fill the string, except \0 (string terminator),
712 // or \1 (guarantees it's different from anything in ptr2).
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700713 memset(state.ptr1, 'K', state.MAX_LEN);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700714 // Choose a random size for our src buffer.
715 size_t ptr1_len = random() % state.MAX_LEN;
716 state.ptr1[ptr1_len] = '\0';
717 // Copy ptr1 into ptr, used to verify that ptr1 does not get modified.
Anna Tikhonova036154b2012-10-05 15:21:11 +0400718 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700719 // Init ptr2 to a set value.
Anna Tikhonova036154b2012-10-05 15:21:11 +0400720 memset(state.ptr2, '\1', state.MAX_LEN);
721
Christopher Ferris950a58e2014-04-04 14:38:18 -0700722 // Choose a random amount of data to copy.
723 size_t copy_len = random() % state.MAX_LEN;
724
725 // Set the second half of ptr to the expected pattern in ptr2.
726 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
727 memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len);
728 size_t expected_end;
729 if (copy_len > ptr1_len) {
730 memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len);
731 expected_end = ptr1_len;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400732 } else {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700733 expected_end = copy_len;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400734 }
735
Christopher Ferris950a58e2014-04-04 14:38:18 -0700736 ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400737
Christopher Ferris950a58e2014-04-04 14:38:18 -0700738 // Verify ptr1 was not modified.
739 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN));
740 // Verify ptr2 contains the expected data.
741 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400742 }
743}
744
Christopher Ferris13f26a72016-01-13 13:47:58 -0800745TEST(STRING_TEST, strrchr) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700746 int seek_char = 'M';
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400747 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400748 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700749 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400750 if (~seek_char > 0) {
751 memset(state.ptr1, ~seek_char, state.len[i]);
752 } else {
753 memset(state.ptr1, '\1', state.len[i]);
754 }
755 state.ptr1[state.len[i] - 1] = '\0';
756
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700757 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400758 char* expected;
759 if (pos >= state.len[i] - 1) {
760 if (seek_char == 0) {
761 expected = state.ptr1 + state.len[i] - 1;
762 } else {
763 expected = NULL;
764 }
765 } else {
766 state.ptr1[pos] = seek_char;
767 expected = state.ptr1 + pos;
768 }
769
770 ASSERT_TRUE(strrchr(state.ptr1, seek_char) == expected);
771 }
772 }
773}
774
Christopher Ferris13f26a72016-01-13 13:47:58 -0800775TEST(STRING_TEST, memchr) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700776 int seek_char = 'N';
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400777 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400778 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700779 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400780 memset(state.ptr1, ~seek_char, state.len[i]);
781
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700782 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400783 char* expected;
784 if (pos >= state.len[i]) {
785 expected = NULL;
786 } else {
787 state.ptr1[pos] = seek_char;
788 expected = state.ptr1 + pos;
789 }
790
791 ASSERT_TRUE(memchr(state.ptr1, seek_char, state.len[i]) == expected);
792 }
793 }
794}
795
Christopher Ferris13f26a72016-01-13 13:47:58 -0800796TEST(STRING_TEST, memchr_zero) {
Christopher Ferrise03e1ea2014-07-30 16:06:56 -0700797 uint8_t* buffer;
798 ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&buffer), 64, 64));
799 memset(buffer, 10, 64);
800 ASSERT_TRUE(NULL == memchr(buffer, 5, 0));
801 ASSERT_TRUE(NULL == memchr(buffer, 10, 0));
802}
803
Christopher Ferris13f26a72016-01-13 13:47:58 -0800804TEST(STRING_TEST, memrchr) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700805 int seek_char = 'P';
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400806 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400807 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700808 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400809 memset(state.ptr1, ~seek_char, state.len[i]);
810
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700811 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400812 char* expected;
813 if (pos >= state.len[i]) {
814 expected = NULL;
815 } else {
816 state.ptr1[pos] = seek_char;
817 expected = state.ptr1 + pos;
818 }
819
820 ASSERT_TRUE(memrchr(state.ptr1, seek_char, state.len[i]) == expected);
821 }
822 }
823}
824
Christopher Ferris13f26a72016-01-13 13:47:58 -0800825TEST(STRING_TEST, memcmp) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400826 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400827 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700828 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
829 int c1 = 'A';
830 int c2 = 'N';
Anna Tikhonova036154b2012-10-05 15:21:11 +0400831 memset(state.ptr1, c1, state.MAX_LEN);
832 memset(state.ptr2, c1, state.MAX_LEN);
833
834 int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]);
835 state.ptr2[pos] = c2;
836
837 int expected = (static_cast<int>(c1) - static_cast<int>(c2));
838 int actual = memcmp(state.ptr1, state.ptr2, state.MAX_LEN);
839
840 ASSERT_EQ(signum(expected), signum(actual));
841 }
842 }
843}
844
Christopher Ferris13f26a72016-01-13 13:47:58 -0800845TEST(STRING_TEST, wmemcmp) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400846 StringTestState<wchar_t> state(SMALL);
847
848 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700849 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400850 long long mask = ((long long) 1 << 8 * sizeof(wchar_t)) - 1;
851 int c1 = rand() & mask;
852 int c2 = rand() & mask;
853 wmemset(state.ptr1, c1, state.MAX_LEN);
854 wmemset(state.ptr2, c1, state.MAX_LEN);
855
856 int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]);
857 state.ptr2[pos] = c2;
858
859 int expected = (static_cast<int>(c1) - static_cast<int>(c2));
860 int actual = wmemcmp(state.ptr1, state.ptr2, (size_t) state.MAX_LEN);
861
862 ASSERT_EQ(signum(expected), signum(actual));
863 }
864 }
865}
866
Christopher Ferris13f26a72016-01-13 13:47:58 -0800867TEST(STRING_TEST, memcpy) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400868 StringTestState<char> state(LARGE);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700869 int rand = 4;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400870 for (size_t i = 0; i < state.n - 1; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700871 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400872 size_t pos = random() % (state.MAX_LEN - state.len[i]);
873
874 memset(state.ptr1, rand, state.len[i]);
875 memset(state.ptr1 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
876
877 memset(state.ptr2, rand, state.len[i]);
878 memset(state.ptr2 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
879 memset(state.ptr2 + pos, '\0', state.len[i]);
880
881 ASSERT_FALSE(memcpy(state.ptr2 + pos, state.ptr1 + pos, state.len[i]) != state.ptr2 + pos);
882 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
883 }
884 }
885}
886
Christopher Ferris13f26a72016-01-13 13:47:58 -0800887TEST(STRING_TEST, memset) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400888 StringTestState<char> state(LARGE);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700889 char ch = 'P';
Anna Tikhonova036154b2012-10-05 15:21:11 +0400890 for (size_t i = 0; i < state.n - 1; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700891 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400892 memset(state.ptr1, ~ch, state.MAX_LEN);
893 memcpy(state.ptr2, state.ptr1, state.MAX_LEN);
894
895 size_t pos = random () % (state.MAX_LEN - state.len[i]);
896 for (size_t k = pos; k < pos + state.len[i]; k++) {
897 state.ptr1[k] = ch;
898 }
899
900 ASSERT_TRUE(memset(state.ptr2 + pos, ch, state.len[i]) == state.ptr2 + pos);
901
902 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
903 }
904 }
905}
906
Christopher Ferris13f26a72016-01-13 13:47:58 -0800907TEST(STRING_TEST, memmove) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400908 StringTestState<char> state(LARGE);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400909 for (size_t i = 0; i < state.n - 1; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700910 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
911 memset(state.ptr1, 'Q', 2 * state.MAX_LEN);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400912
913 size_t pos = random() % (state.MAX_LEN - state.len[i]);
914
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700915 memset(state.ptr1, 'R', state.len[i]);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400916 memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
917 memcpy(state.ptr, state.ptr1, state.len[i]);
918 memcpy(state.ptr1 + pos, state.ptr, state.len[i]);
919
920 ASSERT_TRUE(memmove(state.ptr2 + pos, state.ptr2, state.len[i]) == state.ptr2 + pos);
921 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr1, 2 * state.MAX_LEN));
922 }
923 }
924}
925
Christopher Ferris13f26a72016-01-13 13:47:58 -0800926TEST(STRING_TEST, memmove_cache_size) {
Varvara Rainchikfce86142014-05-27 12:41:55 +0400927 size_t len = 600000;
928 int max_alignment = 31;
929 int alignments[] = {0, 5, 11, 29, 30};
930 char* ptr = reinterpret_cast<char*>(malloc(sizeof(char) * len));
931 char* ptr1 = reinterpret_cast<char*>(malloc(2 * sizeof(char) * len));
932 char* glob_ptr2 = reinterpret_cast<char*>(malloc(2 * sizeof(char) * len + max_alignment));
933 size_t pos = 64;
934
935 ASSERT_TRUE(ptr != NULL);
936 ASSERT_TRUE(ptr1 != NULL);
937 ASSERT_TRUE(glob_ptr2 != NULL);
938
939 for (int i = 0; i < 5; i++) {
940 char* ptr2 = glob_ptr2 + alignments[i];
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700941 memset(ptr1, 'S', 2 * len);
942 memset(ptr1, 'T', len);
Varvara Rainchikfce86142014-05-27 12:41:55 +0400943 memcpy(ptr2, ptr1, 2 * len);
944 memcpy(ptr, ptr1, len);
945 memcpy(ptr1 + pos, ptr, len);
946
947 ASSERT_TRUE(memmove(ptr2 + pos, ptr, len) == ptr2 + pos);
948 ASSERT_EQ(0, memcmp(ptr2, ptr1, 2 * len));
949 }
950 free(ptr);
951 free(ptr1);
952 free(glob_ptr2);
953}
954
Shu Zhang6c80ccd2014-05-12 18:12:15 +0800955static void verify_memmove(char* src_copy, char* dst, char* src, size_t size) {
956 memset(dst, 0, size);
957 memcpy(src, src_copy, size);
958 ASSERT_EQ(dst, memmove(dst, src, size));
959 ASSERT_EQ(0, memcmp(dst, src_copy, size));
960}
961
962#define MEMMOVE_DATA_SIZE (1024*1024*3)
963
Christopher Ferris13f26a72016-01-13 13:47:58 -0800964TEST(STRING_TEST, memmove_check) {
Shu Zhang6c80ccd2014-05-12 18:12:15 +0800965 char* buffer = reinterpret_cast<char*>(malloc(MEMMOVE_DATA_SIZE));
966 ASSERT_TRUE(buffer != NULL);
967
968 char* src_data = reinterpret_cast<char*>(malloc(MEMMOVE_DATA_SIZE));
969 ASSERT_TRUE(src_data != NULL);
970 // Initialize to a known pattern to copy into src for each test and
971 // to compare dst against.
972 for (size_t i = 0; i < MEMMOVE_DATA_SIZE; i++) {
973 src_data[i] = (i + 1) % 255;
974 }
975
976 // Check all different dst offsets between 0 and 127 inclusive.
977 char* src = buffer;
978 for (size_t i = 0; i < 127; i++) {
979 char* dst = buffer + 256 + i;
980 // Small copy.
981 verify_memmove(src_data, dst, src, 1024);
982
983 // Medium copy.
984 verify_memmove(src_data, dst, src, 64 * 1024);
985
986 // Medium copy.
987 verify_memmove(src_data, dst, src, 1024 * 1024 + 128 * 1024);
988 }
989
990 // Check all leftover size offsets between 1 and 127 inclusive.
991 char* dst = buffer + 256;
992 src = buffer;
993 for (size_t size = 1; size < 127; size++) {
994 // Small copy.
995 verify_memmove(src_data, dst, src, 1024);
996
997 // Medium copy.
998 verify_memmove(src_data, dst, src, 64 * 1024);
999
1000 // Large copy.
1001 verify_memmove(src_data, dst, src, 1024 * 1024 + 128 * 1024);
1002 }
1003}
1004
Christopher Ferris13f26a72016-01-13 13:47:58 -08001005TEST(STRING_TEST, bcopy) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +04001006 StringTestState<char> state(LARGE);
Anna Tikhonova036154b2012-10-05 15:21:11 +04001007 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -07001008 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
1009 memset(state.ptr1, '4', state.MAX_LEN);
1010 memset(state.ptr1 + state.MAX_LEN, 'a', state.MAX_LEN);
Anna Tikhonova036154b2012-10-05 15:21:11 +04001011 memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
1012
1013 size_t start = random() % (2 * state.MAX_LEN - state.len[i]);
1014 memcpy(state.ptr2 + start, state.ptr1, state.len[i]);
1015
1016 bcopy(state.ptr1, state.ptr1 + start, state.len[i]);
1017 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, 2 * state.MAX_LEN));
1018 }
1019 }
1020}
1021
Christopher Ferris13f26a72016-01-13 13:47:58 -08001022TEST(STRING_TEST, bzero) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +04001023 StringTestState<char> state(LARGE);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -07001024 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
1025 memset(state.ptr1, 'R', state.MAX_LEN);
Anna Tikhonova036154b2012-10-05 15:21:11 +04001026
1027 size_t start = random() % state.MAX_LEN;
1028 size_t end = start + random() % (state.MAX_LEN - start);
1029
1030 memcpy(state.ptr2, state.ptr1, start);
1031 memset(state.ptr2 + start, '\0', end - start);
1032 memcpy(state.ptr2 + end, state.ptr1 + end, state.MAX_LEN - end);
1033
1034 bzero(state.ptr1 + start, end - start);
1035
1036 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
1037 }
1038}
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001039
1040static void DoMemcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1041 memset(src, (len % 255) + 1, len);
1042 memset(dst, 0, len);
1043
1044 ASSERT_EQ(dst, memcpy(dst, src, len));
1045 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1046}
1047
Christopher Ferris13f26a72016-01-13 13:47:58 -08001048TEST(STRING_TEST, memcpy_align) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001049 RunSrcDstBufferAlignTest(LARGE, DoMemcpyTest);
1050}
1051
Christopher Ferris13f26a72016-01-13 13:47:58 -08001052TEST(STRING_TEST, memcpy_overread) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001053 RunSrcDstBufferOverreadTest(DoMemcpyTest);
1054}
1055
Shu Zhang6c80ccd2014-05-12 18:12:15 +08001056static void DoMemmoveTest(uint8_t* src, uint8_t* dst, size_t len) {
1057 memset(src, (len % 255) + 1, len);
1058 memset(dst, 0, len);
1059
1060 ASSERT_EQ(dst, memmove(dst, src, len));
1061 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1062}
1063
Christopher Ferris13f26a72016-01-13 13:47:58 -08001064TEST(STRING_TEST, memmove_align) {
Shu Zhang6c80ccd2014-05-12 18:12:15 +08001065 RunSrcDstBufferAlignTest(LARGE, DoMemmoveTest);
1066}
1067
Christopher Ferris13f26a72016-01-13 13:47:58 -08001068TEST(STRING_TEST, memmove_overread) {
Shu Zhang6c80ccd2014-05-12 18:12:15 +08001069 RunSrcDstBufferOverreadTest(DoMemmoveTest);
1070}
1071
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001072static void DoMemsetTest(uint8_t* buf, size_t len) {
1073 for (size_t i = 0; i < len; i++) {
1074 buf[i] = 0;
1075 }
1076 int value = (len % 255) + 1;
1077 ASSERT_EQ(buf, memset(buf, value, len));
1078 for (size_t i = 0; i < len; i++) {
1079 ASSERT_EQ(value, buf[i]);
1080 }
1081}
1082
Christopher Ferris13f26a72016-01-13 13:47:58 -08001083TEST(STRING_TEST, memset_align) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001084 RunSingleBufferAlignTest(LARGE, DoMemsetTest);
1085}
1086
1087static void DoStrlenTest(uint8_t* buf, size_t len) {
1088 if (len >= 1) {
1089 memset(buf, (32 + (len % 96)), len - 1);
1090 buf[len-1] = '\0';
1091 ASSERT_EQ(len-1, strlen(reinterpret_cast<char*>(buf)));
1092 }
1093}
1094
Christopher Ferris13f26a72016-01-13 13:47:58 -08001095TEST(STRING_TEST, strlen_align) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001096 RunSingleBufferAlignTest(LARGE, DoStrlenTest);
1097}
1098
Christopher Ferris13f26a72016-01-13 13:47:58 -08001099TEST(STRING_TEST, strlen_overread) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001100 RunSingleBufferOverreadTest(DoStrlenTest);
1101}
1102
1103static void DoStrcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1104 if (len >= 1) {
1105 memset(src, (32 + (len % 96)), len - 1);
1106 src[len-1] = '\0';
1107 memset(dst, 0, len);
1108 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcpy(reinterpret_cast<char*>(dst),
1109 reinterpret_cast<char*>(src))));
1110 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1111 }
1112}
1113
Christopher Ferris13f26a72016-01-13 13:47:58 -08001114TEST(STRING_TEST, strcpy_align) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001115 RunSrcDstBufferAlignTest(LARGE, DoStrcpyTest);
1116}
1117
Christopher Ferris13f26a72016-01-13 13:47:58 -08001118TEST(STRING_TEST, strcpy_overread) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001119 RunSrcDstBufferOverreadTest(DoStrcpyTest);
1120}
1121
Christopher Ferris14687652014-11-10 13:58:17 -08001122#if defined(STRLCPY_SUPPORTED)
1123static void DoStrlcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1124 if (len >= 1) {
1125 memset(src, (32 + (len % 96)), len - 1);
1126 src[len-1] = '\0';
1127 memset(dst, 0, len);
1128 ASSERT_EQ(len-1, strlcpy(reinterpret_cast<char*>(dst),
1129 reinterpret_cast<char*>(src), len));
1130 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1131 }
1132}
1133#endif
1134
Christopher Ferris13f26a72016-01-13 13:47:58 -08001135TEST(STRING_TEST, strlcpy_align) {
Christopher Ferris14687652014-11-10 13:58:17 -08001136#if defined(STRLCPY_SUPPORTED)
1137 RunSrcDstBufferAlignTest(LARGE, DoStrlcpyTest);
1138#else
1139 GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
1140#endif
1141}
1142
Christopher Ferris13f26a72016-01-13 13:47:58 -08001143TEST(STRING_TEST, strlcpy_overread) {
Christopher Ferris14687652014-11-10 13:58:17 -08001144#if defined(STRLCPY_SUPPORTED)
1145 RunSrcDstBufferOverreadTest(DoStrlcpyTest);
1146#else
1147 GTEST_LOG_(INFO) << "Skipping test, strlcpy not supported on this platform.";
1148#endif
1149}
1150
1151
Christopher Ferris950a58e2014-04-04 14:38:18 -07001152static void DoStpcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1153 if (len >= 1) {
1154 memset(src, (32 + (len % 96)), len - 1);
1155 src[len-1] = '\0';
1156 memset(dst, 0, len);
1157 ASSERT_EQ(dst+len-1, reinterpret_cast<uint8_t*>(stpcpy(reinterpret_cast<char*>(dst),
1158 reinterpret_cast<char*>(src))));
1159 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1160 }
1161}
1162
Christopher Ferris13f26a72016-01-13 13:47:58 -08001163TEST(STRING_TEST, stpcpy_align) {
Christopher Ferris950a58e2014-04-04 14:38:18 -07001164 RunSrcDstBufferAlignTest(LARGE, DoStpcpyTest);
1165}
1166
Christopher Ferris13f26a72016-01-13 13:47:58 -08001167TEST(STRING_TEST, stpcpy_overread) {
Christopher Ferris950a58e2014-04-04 14:38:18 -07001168 RunSrcDstBufferOverreadTest(DoStpcpyTest);
1169}
1170
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001171// Use our own incrementer to cut down on the total number of calls.
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001172static size_t LargeSetIncrement(size_t len) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001173 if (len >= 4096) {
1174 return 4096;
1175 } else if (len >= 1024) {
1176 return 1024;
1177 } else if (len >= 256) {
1178 return 256;
1179 }
1180 return 1;
1181}
1182
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001183#define STRCAT_DST_LEN 64
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001184
1185static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) {
1186 if (len >= 1) {
1187 int value = 32 + (len % 96);
1188 memset(src, value, len - 1);
1189 src[len-1] = '\0';
1190
1191 if (len >= STRCAT_DST_LEN) {
1192 // Create a small buffer for doing quick compares in each loop.
1193 uint8_t cmp_buf[STRCAT_DST_LEN];
1194 // Make sure dst string contains a different value then the src string.
1195 int value2 = 32 + (value + 2) % 96;
1196 memset(cmp_buf, value2, sizeof(cmp_buf));
1197
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001198 for (size_t i = 1; i <= STRCAT_DST_LEN;) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001199 memset(dst, value2, i-1);
1200 memset(dst+i-1, 0, len-i);
1201 src[len-i] = '\0';
1202 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst),
1203 reinterpret_cast<char*>(src))));
1204 ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
1205 ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001206 // This is an expensive loop, so don't loop through every value,
1207 // get to a certain size and then start doubling.
1208 if (i < 16) {
1209 i++;
1210 } else {
1211 i <<= 1;
1212 }
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001213 }
1214 } else {
1215 dst[0] = '\0';
1216 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst),
1217 reinterpret_cast<char*>(src))));
1218 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1219 }
1220 }
1221}
1222
Christopher Ferris13f26a72016-01-13 13:47:58 -08001223TEST(STRING_TEST, strcat_align) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001224 RunSrcDstBufferAlignTest(MEDIUM, DoStrcatTest, LargeSetIncrement);
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001225}
1226
Christopher Ferris13f26a72016-01-13 13:47:58 -08001227TEST(STRING_TEST, strcat_overread) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001228 RunSrcDstBufferOverreadTest(DoStrcatTest);
1229}
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001230
Christopher Ferris14687652014-11-10 13:58:17 -08001231#if defined(STRLCAT_SUPPORTED)
1232static void DoStrlcatTest(uint8_t* src, uint8_t* dst, size_t len) {
1233 if (len >= 1) {
1234 int value = 32 + (len % 96);
1235 memset(src, value, len - 1);
1236 src[len-1] = '\0';
1237
1238 if (len >= STRCAT_DST_LEN) {
1239 // Create a small buffer for doing quick compares in each loop.
1240 uint8_t cmp_buf[STRCAT_DST_LEN];
1241 // Make sure dst string contains a different value then the src string.
1242 int value2 = 32 + (value + 2) % 96;
1243 memset(cmp_buf, value2, sizeof(cmp_buf));
1244
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001245 for (size_t i = 1; i <= STRCAT_DST_LEN;) {
Christopher Ferris14687652014-11-10 13:58:17 -08001246 memset(dst, value2, i-1);
1247 memset(dst+i-1, 0, len-i);
1248 src[len-i] = '\0';
1249 ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
1250 reinterpret_cast<char*>(src), len));
1251 ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
1252 ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001253 // This is an expensive loop, so don't loop through every value,
1254 // get to a certain size and then start doubling.
1255 if (i < 16) {
1256 i++;
1257 } else {
1258 i <<= 1;
1259 }
Christopher Ferris14687652014-11-10 13:58:17 -08001260 }
1261 } else {
1262 dst[0] = '\0';
1263 ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
1264 reinterpret_cast<char*>(src), len));
1265 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1266 }
1267 }
1268}
1269#endif
1270
Christopher Ferris13f26a72016-01-13 13:47:58 -08001271TEST(STRING_TEST, strlcat_align) {
Christopher Ferris14687652014-11-10 13:58:17 -08001272#if defined(STRLCAT_SUPPORTED)
1273 RunSrcDstBufferAlignTest(MEDIUM, DoStrlcatTest, LargeSetIncrement);
1274#else
1275 GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
1276#endif
1277}
1278
Christopher Ferris13f26a72016-01-13 13:47:58 -08001279TEST(STRING_TEST, strlcat_overread) {
Christopher Ferris14687652014-11-10 13:58:17 -08001280#if defined(STRLCAT_SUPPORTED)
1281 RunSrcDstBufferOverreadTest(DoStrlcatTest);
1282#else
1283 GTEST_LOG_(INFO) << "Skipping test, strlcat not supported on this platform.";
1284#endif
1285}
1286
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001287static void DoStrcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
1288 if (len >= 1) {
1289 memset(buf1, (32 + (len % 96)), len - 1);
1290 buf1[len-1] = '\0';
1291 memset(buf2, (32 + (len % 96)), len - 1);
1292 buf2[len-1] = '\0';
1293 ASSERT_EQ(0, strcmp(reinterpret_cast<char*>(buf1),
1294 reinterpret_cast<char*>(buf2)));
1295 }
1296}
1297
1298static void DoStrcmpFailTest(uint8_t* buf1, uint8_t* buf2, size_t len1, size_t len2) {
1299 // Do string length differences.
1300 int c = (32 + (len1 % 96));
1301 memset(buf1, c, len1 - 1);
1302 buf1[len1-1] = '\0';
1303 memset(buf2, c, len2 - 1);
1304 buf2[len2-1] = '\0';
1305 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1306 reinterpret_cast<char*>(buf2)));
1307
1308 // Do single character differences.
1309 size_t len;
1310 if (len1 > len2) {
1311 len = len2;
1312 } else {
1313 len = len1;
1314 }
1315 // Need at least a two character buffer to do this test.
1316 if (len > 1) {
1317 buf1[len-1] = '\0';
1318 buf2[len-1] = '\0';
1319 int diff_c = (c + 1) % 96;
1320
1321 buf1[len-2] = diff_c;
1322 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1323 reinterpret_cast<char*>(buf2)));
1324
1325 buf1[len-2] = c;
1326 buf2[len-2] = diff_c;
1327 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1328 reinterpret_cast<char*>(buf2)));
1329 }
1330}
1331
Christopher Ferris13f26a72016-01-13 13:47:58 -08001332TEST(STRING_TEST, strcmp_align) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001333 RunCmpBufferAlignTest(MEDIUM, DoStrcmpTest, DoStrcmpFailTest, LargeSetIncrement);
1334}
1335
Christopher Ferris13f26a72016-01-13 13:47:58 -08001336TEST(STRING_TEST, strcmp_overread) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001337 RunCmpBufferOverreadTest(DoStrcmpTest, DoStrcmpFailTest);
1338}
1339
1340static void DoMemcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
1341 memset(buf1, len+1, len);
1342 memset(buf2, len+1, len);
1343 ASSERT_EQ(0, memcmp(buf1, buf2, len));
1344}
1345
1346static void DoMemcmpFailTest(uint8_t* buf1, uint8_t* buf2, size_t len1, size_t len2) {
1347 size_t len;
1348 if (len1 > len2) {
1349 len = len2;
1350 } else {
1351 len = len1;
1352 }
1353
1354 memset(buf1, len2+1, len);
1355 buf1[len-1] = len2;
1356 memset(buf2, len2+1, len);
1357 ASSERT_NE(0, memcmp(buf1, buf2, len));
1358
1359 buf1[len-1] = len2+1;
1360 buf2[len-1] = len2;
1361 ASSERT_NE(0, memcmp(buf1, buf2, len));
1362}
1363
Christopher Ferris13f26a72016-01-13 13:47:58 -08001364TEST(STRING_TEST, memcmp_align) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001365 RunCmpBufferAlignTest(MEDIUM, DoMemcmpTest, DoMemcmpFailTest, LargeSetIncrement);
1366}
1367
Christopher Ferris13f26a72016-01-13 13:47:58 -08001368TEST(STRING_TEST, memcmp_overread) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001369 RunCmpBufferOverreadTest(DoMemcmpTest, DoMemcmpFailTest);
1370}
Christopher Ferris3a657d02014-06-27 12:33:22 -07001371
1372static void DoStrchrTest(uint8_t* buf, size_t len) {
1373 if (len >= 1) {
1374 char value = 32 + (len % 96);
1375 char search_value = 33 + (len % 96);
1376 memset(buf, value, len - 1);
1377 buf[len-1] = '\0';
1378 ASSERT_EQ(NULL, strchr(reinterpret_cast<char*>(buf), search_value));
1379 ASSERT_EQ(reinterpret_cast<char*>(&buf[len-1]), strchr(reinterpret_cast<char*>(buf), '\0'));
1380 if (len >= 2) {
1381 buf[0] = search_value;
1382 ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strchr(reinterpret_cast<char*>(buf), search_value));
1383 buf[0] = value;
1384 buf[len-2] = search_value;
1385 ASSERT_EQ(reinterpret_cast<char*>(&buf[len-2]), strchr(reinterpret_cast<char*>(buf), search_value));
1386 }
1387 }
1388}
1389
Christopher Ferris13f26a72016-01-13 13:47:58 -08001390TEST(STRING_TEST, strchr_align) {
Christopher Ferris3a657d02014-06-27 12:33:22 -07001391 RunSingleBufferAlignTest(MEDIUM, DoStrchrTest);
1392}
1393
Christopher Ferris13f26a72016-01-13 13:47:58 -08001394TEST(STRING_TEST, strchr_overread) {
Christopher Ferris3a657d02014-06-27 12:33:22 -07001395 RunSingleBufferOverreadTest(DoStrchrTest);
1396}
Elliott Hughes09c39d62014-08-19 14:30:30 -07001397
1398static void TestBasename(const char* in, const char* expected_out) {
1399 errno = 0;
1400 const char* out = basename(in);
1401 ASSERT_STREQ(expected_out, out) << in;
1402 ASSERT_EQ(0, errno) << in;
1403}
1404
Christopher Ferris13f26a72016-01-13 13:47:58 -08001405TEST(STRING_TEST, __gnu_basename) {
Elliott Hughes09c39d62014-08-19 14:30:30 -07001406 TestBasename("", "");
1407 TestBasename("/usr/lib", "lib");
1408 TestBasename("/usr/", "");
1409 TestBasename("usr", "usr");
1410 TestBasename("/", "");
1411 TestBasename(".", ".");
1412 TestBasename("..", "..");
1413 TestBasename("///", "");
1414 TestBasename("//usr//lib//", "");
1415}
Elliott Hughes41ef9022015-02-14 13:21:22 -08001416
Christopher Ferris13f26a72016-01-13 13:47:58 -08001417TEST(STRING_TEST, strnlen_147048) {
Elliott Hughes41ef9022015-02-14 13:21:22 -08001418 // https://code.google.com/p/android/issues/detail?id=147048
1419 char stack_src[64] = {0};
1420 EXPECT_EQ(0U, strnlen(stack_src, 1024*1024*1024));
1421 char* heap_src = new char[1];
1422 *heap_src = '\0';
1423 EXPECT_EQ(0U, strnlen(heap_src, 1024*1024*1024));
1424 delete[] heap_src;
1425}
Elliott Hughes3cfb52a2015-02-18 21:29:13 -08001426
Christopher Ferris13f26a72016-01-13 13:47:58 -08001427TEST(STRING_TEST, strnlen_74741) {
Elliott Hughesd2a9fb32015-07-27 20:55:03 -07001428 ASSERT_EQ(4U, strnlen("test", SIZE_MAX));
1429}
1430
Christopher Ferris13f26a72016-01-13 13:47:58 -08001431TEST(STRING_TEST, mempcpy) {
Elliott Hughes3cfb52a2015-02-18 21:29:13 -08001432 char dst[6];
1433 ASSERT_EQ(&dst[4], reinterpret_cast<char*>(mempcpy(dst, "hello", 4)));
1434}