blob: d19b60d3989b8ee84f5bec682c564e223e3752b2 [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 Ferris71766c22016-02-12 17:24:27 -080027#include <algorithm>
28#include <vector>
29
Christopher Ferrisb687ad32013-11-06 17:32:11 -080030#include "buffer_tests.h"
31
Christopher Ferris13f26a72016-01-13 13:47:58 -080032#if defined(NOFORTIFY)
33#define STRING_TEST string_nofortify
34#else
35#define STRING_TEST string
36#endif
37
Christopher Ferris14687652014-11-10 13:58:17 -080038#if defined(__BIONIC__)
39#define STRLCPY_SUPPORTED
40#define STRLCAT_SUPPORTED
41#endif
42
Chih-Hung Hsiehd61ca372016-06-03 10:18:07 -070043constexpr auto KB = 1024;
44constexpr auto SMALL = 1 * KB;
45constexpr auto MEDIUM = 4 * KB;
46constexpr auto LARGE = 64 * KB;
Anna Tikhonova036154b2012-10-05 15:21:11 +040047
48static int signum(int i) {
49 if (i < 0) {
50 return -1;
51 } else if (i > 0) {
52 return 1;
53 }
54 return 0;
55}
56
Christopher Ferris13f26a72016-01-13 13:47:58 -080057TEST(STRING_TEST, strerror) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +030058 // Valid.
59 ASSERT_STREQ("Success", strerror(0));
60 ASSERT_STREQ("Operation not permitted", strerror(1));
61
62 // Invalid.
Elliott Hughese6e60062013-01-10 16:01:59 -080063 ASSERT_STREQ("Unknown error -1", strerror(-1));
Elliott Hugheseebf5fd2018-11-30 16:56:43 -080064 ASSERT_STREQ("Unknown error 134", strerror(EHWPOISON + 1));
Irina Tirdeab5f053b2012-09-08 09:17:54 +030065}
66
Elliott Hughes7cebf832020-08-12 14:25:41 -070067TEST(STRING_TEST, strerror_l) {
68 // bionic just forwards to strerror(3).
69 ASSERT_STREQ("Success", strerror_l(0, LC_GLOBAL_LOCALE));
70}
71
Christopher Ferrisf04935c2013-12-20 18:43:21 -080072#if defined(__BIONIC__)
Elliott Hughesad88a082012-10-24 18:37:21 -070073static void* ConcurrentStrErrorFn(void*) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +030074 bool equal = (strcmp("Unknown error 2002", strerror(2002)) == 0);
75 return reinterpret_cast<void*>(equal);
76}
Christopher Ferrisf04935c2013-12-20 18:43:21 -080077#endif // __BIONIC__
Irina Tirdeab5f053b2012-09-08 09:17:54 +030078
Christopher Ferrisf04935c2013-12-20 18:43:21 -080079// glibc's strerror isn't thread safe, only its strsignal.
Christopher Ferris13f26a72016-01-13 13:47:58 -080080TEST(STRING_TEST, strerror_concurrent) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -080081#if defined(__BIONIC__)
Irina Tirdeab5f053b2012-09-08 09:17:54 +030082 const char* strerror1001 = strerror(1001);
83 ASSERT_STREQ("Unknown error 1001", strerror1001);
84
85 pthread_t t;
Yi Kong32bc0fc2018-08-02 17:31:13 -070086 ASSERT_EQ(0, pthread_create(&t, nullptr, ConcurrentStrErrorFn, nullptr));
Irina Tirdeab5f053b2012-09-08 09:17:54 +030087 void* result;
88 ASSERT_EQ(0, pthread_join(t, &result));
89 ASSERT_TRUE(static_cast<bool>(result));
90
91 ASSERT_STREQ("Unknown error 1001", strerror1001);
Christopher Ferrisf04935c2013-12-20 18:43:21 -080092#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -080093 GTEST_SKIP() << "thread-safe strerror not available";
Christopher Ferrisf04935c2013-12-20 18:43:21 -080094#endif // __BIONIC__
Irina Tirdeab5f053b2012-09-08 09:17:54 +030095}
Elliott Hughesad88a082012-10-24 18:37:21 -070096
Christopher Ferris13f26a72016-01-13 13:47:58 -080097TEST(STRING_TEST, gnu_strerror_r) {
Colin Cross7da20342021-07-28 11:18:11 -070098#if !defined(MUSL)
Irina Tirdeab5f053b2012-09-08 09:17:54 +030099 char buf[256];
100
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700101 // Note that glibc doesn't necessarily write into the buffer.
102
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300103 // Valid.
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700104 ASSERT_STREQ("Success", strerror_r(0, buf, sizeof(buf)));
105#if defined(__BIONIC__)
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300106 ASSERT_STREQ("Success", buf);
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700107#endif
108 ASSERT_STREQ("Operation not permitted", strerror_r(1, buf, sizeof(buf)));
109#if defined(__BIONIC__)
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300110 ASSERT_STREQ("Operation not permitted", buf);
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700111#endif
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300112
113 // Invalid.
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700114 ASSERT_STREQ("Unknown error -1", strerror_r(-1, buf, sizeof(buf)));
Nick Kralevich60605892013-01-15 10:35:09 -0800115 ASSERT_STREQ("Unknown error -1", buf);
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700116 ASSERT_STREQ("Unknown error 1234", strerror_r(1234, buf, sizeof(buf)));
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300117 ASSERT_STREQ("Unknown error 1234", buf);
118
119 // Buffer too small.
Elliott Hughes416d7dd2014-08-18 17:28:32 -0700120 errno = 0;
121 memset(buf, 0, sizeof(buf));
122 ASSERT_EQ(buf, strerror_r(4567, buf, 2));
123 ASSERT_STREQ("U", buf);
124 // The GNU strerror_r doesn't set errno (the POSIX one sets it to ERANGE).
125 ASSERT_EQ(0, errno);
Colin Cross7da20342021-07-28 11:18:11 -0700126#else
127 GTEST_SKIP() << "musl doesn't have GNU strerror_r";
128#endif
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300129}
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300130
Christopher Ferris13f26a72016-01-13 13:47:58 -0800131TEST(STRING_TEST, strsignal) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300132 // A regular signal.
133 ASSERT_STREQ("Hangup", strsignal(1));
134
135 // A real-time signal.
Elliott Hughes0990d4f2014-04-30 09:45:40 -0700136 ASSERT_STREQ("Real-time signal 14", strsignal(SIGRTMIN + 14));
137 // One of the signals the C library keeps to itself.
138 ASSERT_STREQ("Unknown signal 32", strsignal(__SIGRTMIN));
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300139
140 // Errors.
141 ASSERT_STREQ("Unknown signal -1", strsignal(-1)); // Too small.
142 ASSERT_STREQ("Unknown signal 0", strsignal(0)); // Still too small.
143 ASSERT_STREQ("Unknown signal 1234", strsignal(1234)); // Too large.
144}
145
Elliott Hughesad88a082012-10-24 18:37:21 -0700146static void* ConcurrentStrSignalFn(void*) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300147 bool equal = (strcmp("Unknown signal 2002", strsignal(2002)) == 0);
148 return reinterpret_cast<void*>(equal);
149}
150
Christopher Ferris13f26a72016-01-13 13:47:58 -0800151TEST(STRING_TEST, strsignal_concurrent) {
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300152 const char* strsignal1001 = strsignal(1001);
153 ASSERT_STREQ("Unknown signal 1001", strsignal1001);
154
155 pthread_t t;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700156 ASSERT_EQ(0, pthread_create(&t, nullptr, ConcurrentStrSignalFn, nullptr));
Irina Tirdeab5f053b2012-09-08 09:17:54 +0300157 void* result;
158 ASSERT_EQ(0, pthread_join(t, &result));
159 ASSERT_TRUE(static_cast<bool>(result));
160
161 ASSERT_STREQ("Unknown signal 1001", strsignal1001);
162}
Anna Tikhonova036154b2012-10-05 15:21:11 +0400163
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700164// TODO: where did this number come from?
Anna Tikhonova036154b2012-10-05 15:21:11 +0400165#define ITER 500
166
167// For every length we want to test, vary and change alignment
168// of allocated memory, fill it with some values, calculate
169// expected result and then run function and compare what we got.
170// These tests contributed by Intel Corporation.
171// TODO: make these tests more intention-revealing and less random.
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400172template<class Character>
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700173class StringTestState {
174 public:
Chih-Hung Hsieh62e3a072016-05-03 12:08:05 -0700175 explicit StringTestState(size_t MAX_LEN) : MAX_LEN(MAX_LEN), align1_index_(0), align2_index_(0) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400176 int max_alignment = 64;
177
178 // TODO: fix the tests to not sometimes use twice their specified "MAX_LEN".
Dan Alberte5fdaa42014-06-14 01:04:31 +0000179 glob_ptr = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
180 glob_ptr1 = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
181 glob_ptr2 = reinterpret_cast<Character*>(memalign(sysconf(_SC_PAGESIZE), 2 * sizeof(Character) * MAX_LEN + max_alignment));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400182
183 InitLenArray();
184
185 srandom(1234);
186 }
187
188 ~StringTestState() {
189 free(glob_ptr);
190 free(glob_ptr1);
191 free(glob_ptr2);
192 }
193
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700194 void BeginIterations() {
195 align1_index_ = 0;
196 align2_index_ = 0;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400197
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700198 ResetPointers();
199 }
200
201 bool HasNextIteration() {
202 return (align1_index_ != (alignments_size - 1) || align2_index_ != (alignments_size - 1));
203 }
204
205 void NextIteration() {
206 if (align1_index_ == (alignments_size - 1) && align2_index_ == (alignments_size - 1)) {
207 return;
208 }
209
210 if (align1_index_ == (alignments_size - 1)) {
211 align1_index_ = 0;
212 align2_index_++;
213 } else {
214 align1_index_++;
215 }
216
217 ResetPointers();
Anna Tikhonova036154b2012-10-05 15:21:11 +0400218 }
219
220 const size_t MAX_LEN;
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400221 Character *ptr, *ptr1, *ptr2;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400222 size_t n;
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700223 size_t len[ITER + 1];
Anna Tikhonova036154b2012-10-05 15:21:11 +0400224
225 private:
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700226 static size_t alignments[];
227 static size_t alignments_size;
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400228 Character *glob_ptr, *glob_ptr1, *glob_ptr2;
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700229 size_t align1_index_, align2_index_;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400230
231 // Calculate input lengths and fill state.len with them.
232 // Test small lengths with more density than big ones. Manually push
233 // smallest (0) and biggest (MAX_LEN) lengths. Avoid repeats.
234 // Return number of lengths to test.
235 void InitLenArray() {
236 n = 0;
237 len[n++] = 0;
238 for (size_t i = 1; i < ITER; ++i) {
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700239 size_t l = static_cast<size_t>(exp(log(static_cast<double>(MAX_LEN)) * i / ITER));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400240 if (l != len[n - 1]) {
241 len[n++] = l;
242 }
243 }
244 len[n++] = MAX_LEN;
245 }
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700246
247 void ResetPointers() {
248 if (align1_index_ == alignments_size || align2_index_ == alignments_size) {
249 ptr = ptr1 = ptr2 = nullptr;
250 } else {
251 ptr = glob_ptr + alignments[align1_index_];
252 ptr1 = glob_ptr1 + alignments[align1_index_];
253 ptr2 = glob_ptr2 + alignments[align2_index_];
254 }
255 }
Anna Tikhonova036154b2012-10-05 15:21:11 +0400256};
257
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700258template<class Character>
259size_t StringTestState<Character>::alignments[] = { 24, 32, 16, 48, 0, 1, 2, 3, 4, 5, 6, 7, 11 };
260
261template<class Character>
262size_t StringTestState<Character>::alignments_size = sizeof(alignments)/sizeof(size_t);
263
Christopher Ferris13f26a72016-01-13 13:47:58 -0800264TEST(STRING_TEST, strcat) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400265 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400266 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700267 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400268 memset(state.ptr2, '\2', state.MAX_LEN);
269 state.ptr2[state.MAX_LEN - 1] = '\0';
270 memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
271
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700272 memset(state.ptr1, 'L', state.len[i]);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400273 state.ptr1[random() % state.len[i]] = '\0';
274 state.ptr1[state.len[i] - 1] = '\0';
275
276 strcpy(state.ptr + state.MAX_LEN - 1, state.ptr1);
277
278 EXPECT_TRUE(strcat(state.ptr2, state.ptr1) == state.ptr2);
279 EXPECT_TRUE(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN) == 0);
280 }
281 }
282}
283
Nick Kralevich13476de2013-06-03 10:58:06 -0700284// one byte target with "\0" source
Christopher Ferris13f26a72016-01-13 13:47:58 -0800285TEST(STRING_TEST, strcpy2) {
Nick Kralevich13476de2013-06-03 10:58:06 -0700286 char buf[1];
287 char* orig = strdup("");
Christopher Ferris950a58e2014-04-04 14:38:18 -0700288 ASSERT_EQ(buf, strcpy(buf, orig));
Nick Kralevich13476de2013-06-03 10:58:06 -0700289 ASSERT_EQ('\0', buf[0]);
290 free(orig);
291}
292
293// multibyte target where we under fill target
Christopher Ferris13f26a72016-01-13 13:47:58 -0800294TEST(STRING_TEST, strcpy3) {
Nick Kralevich13476de2013-06-03 10:58:06 -0700295 char buf[10];
296 char* orig = strdup("12345");
297 memset(buf, 'A', sizeof(buf));
Christopher Ferris950a58e2014-04-04 14:38:18 -0700298 ASSERT_EQ(buf, strcpy(buf, orig));
299 ASSERT_STREQ("12345", buf);
Nick Kralevich13476de2013-06-03 10:58:06 -0700300 ASSERT_EQ('A', buf[6]);
301 ASSERT_EQ('A', buf[7]);
302 ASSERT_EQ('A', buf[8]);
303 ASSERT_EQ('A', buf[9]);
304 free(orig);
305}
306
307// multibyte target where we fill target exactly
Christopher Ferris13f26a72016-01-13 13:47:58 -0800308TEST(STRING_TEST, strcpy4) {
Nick Kralevich13476de2013-06-03 10:58:06 -0700309 char buf[10];
310 char* orig = strdup("123456789");
311 memset(buf, 'A', sizeof(buf));
Christopher Ferris950a58e2014-04-04 14:38:18 -0700312 ASSERT_EQ(buf, strcpy(buf, orig));
313 ASSERT_STREQ("123456789", buf);
314 free(orig);
315}
316
317// one byte target with "\0" source
Christopher Ferris13f26a72016-01-13 13:47:58 -0800318TEST(STRING_TEST, stpcpy2) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700319 char buf[1];
320 char* orig = strdup("");
321 ASSERT_EQ(buf, stpcpy(buf, orig));
322 ASSERT_EQ('\0', buf[0]);
323 free(orig);
324}
325
326// multibyte target where we under fill target
Christopher Ferris13f26a72016-01-13 13:47:58 -0800327TEST(STRING_TEST, stpcpy3) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700328 char buf[10];
329 char* orig = strdup("12345");
330 memset(buf, 'A', sizeof(buf));
331 ASSERT_EQ(buf+strlen(orig), stpcpy(buf, orig));
332 ASSERT_STREQ("12345", buf);
333 ASSERT_EQ('A', buf[6]);
334 ASSERT_EQ('A', buf[7]);
335 ASSERT_EQ('A', buf[8]);
336 ASSERT_EQ('A', buf[9]);
337 free(orig);
338}
339
340// multibyte target where we fill target exactly
Christopher Ferris13f26a72016-01-13 13:47:58 -0800341TEST(STRING_TEST, stpcpy4) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700342 char buf[10];
343 char* orig = strdup("123456789");
344 memset(buf, 'A', sizeof(buf));
345 ASSERT_EQ(buf+strlen(orig), stpcpy(buf, orig));
346 ASSERT_STREQ("123456789", buf);
Nick Kralevich13476de2013-06-03 10:58:06 -0700347 free(orig);
348}
349
Christopher Ferris13f26a72016-01-13 13:47:58 -0800350TEST(STRING_TEST, strcat2) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700351 char buf[10];
352 memset(buf, 'A', sizeof(buf));
353 buf[0] = 'a';
354 buf[1] = '\0';
355 char* res = strcat(buf, "01234");
356 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700357 ASSERT_STREQ("a01234", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700358 ASSERT_EQ('A', buf[7]);
359 ASSERT_EQ('A', buf[8]);
360 ASSERT_EQ('A', buf[9]);
361}
362
Christopher Ferris13f26a72016-01-13 13:47:58 -0800363TEST(STRING_TEST, strcat3) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700364 char buf[10];
365 memset(buf, 'A', sizeof(buf));
366 buf[0] = 'a';
367 buf[1] = '\0';
368 char* res = strcat(buf, "01234567");
369 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700370 ASSERT_STREQ("a01234567", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700371}
372
Christopher Ferris13f26a72016-01-13 13:47:58 -0800373TEST(STRING_TEST, strncat2) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700374 char buf[10];
375 memset(buf, 'A', sizeof(buf));
376 buf[0] = 'a';
377 buf[1] = '\0';
378 char* res = strncat(buf, "01234", sizeof(buf) - strlen(buf) - 1);
379 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700380 ASSERT_STREQ("a01234", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700381 ASSERT_EQ('A', buf[7]);
382 ASSERT_EQ('A', buf[8]);
383 ASSERT_EQ('A', buf[9]);
384}
385
Christopher Ferris13f26a72016-01-13 13:47:58 -0800386TEST(STRING_TEST, strncat3) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700387 char buf[10];
388 memset(buf, 'A', sizeof(buf));
389 buf[0] = 'a';
390 buf[1] = '\0';
391 char* res = strncat(buf, "0123456789", 5);
392 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700393 ASSERT_STREQ("a01234", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700394 ASSERT_EQ('A', buf[7]);
395 ASSERT_EQ('A', buf[8]);
396 ASSERT_EQ('A', buf[9]);
397}
398
Christopher Ferris13f26a72016-01-13 13:47:58 -0800399TEST(STRING_TEST, strncat4) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700400 char buf[10];
401 memset(buf, 'A', sizeof(buf));
402 buf[0] = 'a';
403 buf[1] = '\0';
404 char* res = strncat(buf, "01234567", 8);
405 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700406 ASSERT_STREQ("a01234567", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700407}
408
Christopher Ferris13f26a72016-01-13 13:47:58 -0800409TEST(STRING_TEST, strncat5) {
Nick Kralevichcf870192013-05-30 16:48:53 -0700410 char buf[10];
411 memset(buf, 'A', sizeof(buf));
412 buf[0] = 'a';
413 buf[1] = '\0';
414 char* res = strncat(buf, "01234567", 9);
415 ASSERT_EQ(buf, res);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700416 ASSERT_STREQ("a01234567", buf);
Nick Kralevichcf870192013-05-30 16:48:53 -0700417}
418
Christopher Ferris13f26a72016-01-13 13:47:58 -0800419TEST(STRING_TEST, strchr_with_0) {
Nick Kralevich4f40e512013-04-19 16:54:22 -0700420 char buf[10];
421 const char* s = "01234";
422 memcpy(buf, s, strlen(s) + 1);
423 EXPECT_TRUE(strchr(buf, '\0') == (buf + strlen(s)));
424}
425
Christopher Ferris13f26a72016-01-13 13:47:58 -0800426TEST(STRING_TEST, strchr_multiple) {
Christopher Ferris3a657d02014-06-27 12:33:22 -0700427 char str[128];
428 memset(str, 'a', sizeof(str) - 1);
429 str[sizeof(str)-1] = '\0';
430
431 // Verify that strchr finds the first occurrence of 'a' in a string
432 // filled with 'a' characters. Iterate over the string putting
433 // non 'a' characters at the front of the string during each iteration
434 // and continue to verify that strchr can find the first occurrence
435 // properly. The idea is to cover all possible alignments of the location
436 // of the first occurrence of the 'a' character and which includes
437 // other 'a' characters close by.
438 for (size_t i = 0; i < sizeof(str) - 1; i++) {
439 EXPECT_EQ(&str[i], strchr(str, 'a'));
440 str[i] = 'b';
441 }
442}
443
Christopher Ferris13f26a72016-01-13 13:47:58 -0800444TEST(STRING_TEST, strchr) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700445 int seek_char = 'R';
Anna Tikhonova036154b2012-10-05 15:21:11 +0400446
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400447 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400448 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700449 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400450 if (~seek_char > 0) {
451 memset(state.ptr1, ~seek_char, state.len[i]);
452 } else {
453 memset(state.ptr1, '\1', state.len[i]);
454 }
455 state.ptr1[state.len[i] - 1] = '\0';
456
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700457 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400458 char* expected;
459 if (pos >= state.len[i] - 1) {
460 if (seek_char == 0) {
461 expected = state.ptr1 + state.len[i] - 1;
462 } else {
Yi Kong32bc0fc2018-08-02 17:31:13 -0700463 expected = nullptr;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400464 }
465 } else {
466 state.ptr1[pos] = seek_char;
467 expected = state.ptr1 + pos;
468 }
469
470 ASSERT_TRUE(strchr(state.ptr1, seek_char) == expected);
471 }
472 }
473}
474
Christopher Ferris13f26a72016-01-13 13:47:58 -0800475TEST(STRING_TEST, strchrnul) {
Elliott Hughes7ac3c122015-08-26 09:59:29 -0700476 const char* s = "01234222";
477 EXPECT_TRUE(strchrnul(s, '2') == &s[2]);
478 EXPECT_TRUE(strchrnul(s, '8') == (s + strlen(s)));
479 EXPECT_TRUE(strchrnul(s, '\0') == (s + strlen(s)));
480}
481
Christopher Ferris13f26a72016-01-13 13:47:58 -0800482TEST(STRING_TEST, strcmp) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400483 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400484 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700485 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400486 memset(state.ptr1, 'v', state.MAX_LEN);
487 memset(state.ptr2, 'n', state.MAX_LEN);
488 state.ptr1[state.len[i] - 1] = '\0';
489 state.ptr2[state.len[i] - 1] = '\0';
490
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700491 size_t pos = 1 + (random() % (state.MAX_LEN - 1));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400492 int actual;
493 int expected;
494 if (pos >= state.len[i] - 1) {
495 memcpy(state.ptr1, state.ptr2, state.len[i]);
496 expected = 0;
497 actual = strcmp(state.ptr1, state.ptr2);
498 } else {
499 memcpy(state.ptr1, state.ptr2, pos);
500 if (state.ptr1[pos] > state.ptr2[pos]) {
501 expected = 1;
502 } else if (state.ptr1[pos] == state.ptr2[pos]) {
503 state.ptr1[pos + 1] = '\0';
504 state.ptr2[pos + 1] = '\0';
505 expected = 0;
506 } else {
507 expected = -1;
508 }
509 actual = strcmp(state.ptr1, state.ptr2);
510 }
511
512 ASSERT_EQ(expected, signum(actual));
513 }
514 }
515}
516
Christopher Ferris13f26a72016-01-13 13:47:58 -0800517TEST(STRING_TEST, stpcpy) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700518 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700519 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700520 size_t pos = random() % state.MAX_LEN;
521
522 memset(state.ptr1, '\2', pos);
523 state.ptr1[pos] = '\0';
524 state.ptr1[state.MAX_LEN - 1] = '\0';
525
526 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
527
528 memset(state.ptr2, '\1', state.MAX_LEN);
529 state.ptr2[state.MAX_LEN - 1] = '\0';
530
531 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
532 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
533 state.ptr[2 * state.MAX_LEN - 1] = '\0';
534
535 ASSERT_TRUE(stpcpy(state.ptr2, state.ptr1) == state.ptr2 + strlen(state.ptr1));
536 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 ||
537 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
538 }
539}
540
Christopher Ferris13f26a72016-01-13 13:47:58 -0800541TEST(STRING_TEST, strcpy) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400542 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700543 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400544 size_t pos = random() % state.MAX_LEN;
545
546 memset(state.ptr1, '\2', pos);
547 state.ptr1[pos] = '\0';
548 state.ptr1[state.MAX_LEN - 1] = '\0';
549
550 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
551
552 memset(state.ptr2, '\1', state.MAX_LEN);
553 state.ptr2[state.MAX_LEN - 1] = '\0';
554
555 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
556 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
557 state.ptr[2 * state.MAX_LEN - 1] = '\0';
558
559 ASSERT_TRUE(strcpy(state.ptr2, state.ptr1) == state.ptr2);
560 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN)) != 0 ||
561 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
562 }
563}
564
Christopher Ferris13f26a72016-01-13 13:47:58 -0800565TEST(STRING_TEST, strlcat) {
Christopher Ferris14687652014-11-10 13:58:17 -0800566#if defined(STRLCAT_SUPPORTED)
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400567 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400568 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700569 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400570 memset(state.ptr2, '\2', state.MAX_LEN + state.len[i]);
571 state.ptr2[state.MAX_LEN - 1] = '\0';
572 memcpy(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]);
573
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700574 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400575 memset(state.ptr1, '\3', pos);
576 state.ptr1[pos] = '\0';
577 if (pos < state.len[i]) {
578 memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, pos + 1);
579 } else {
580 memcpy(state.ptr + state.MAX_LEN - 1, state.ptr1, state.len[i]);
581 state.ptr[state.MAX_LEN + state.len[i] - 1] = '\0';
582 }
583
584 strlcat(state.ptr2, state.ptr1, state.MAX_LEN + state.len[i]);
585
586 ASSERT_TRUE(memcmp(state.ptr, state.ptr2, state.MAX_LEN + state.len[i]) == 0);
587 }
588 }
Christopher Ferris14687652014-11-10 13:58:17 -0800589#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800590 GTEST_SKIP() << "strlcat not available";
Christopher Ferris14687652014-11-10 13:58:17 -0800591#endif
Anna Tikhonova036154b2012-10-05 15:21:11 +0400592}
Anna Tikhonova036154b2012-10-05 15:21:11 +0400593
Christopher Ferris13f26a72016-01-13 13:47:58 -0800594TEST(STRING_TEST, strlcpy) {
Christopher Ferris14687652014-11-10 13:58:17 -0800595#if defined(STRLCPY_SUPPORTED)
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400596 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700597 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
598 int rand = 'O';
Anna Tikhonova036154b2012-10-05 15:21:11 +0400599 memset(state.ptr1, rand, state.MAX_LEN);
600
601 size_t pos = random() % state.MAX_LEN;
602 if (pos < state.MAX_LEN) {
603 state.ptr1[pos] = '\0';
604 }
605 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
606
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700607 memset(state.ptr2, 'I', state.MAX_LEN);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400608 memcpy(state.ptr + state.MAX_LEN, state.ptr2, state.MAX_LEN);
609
610 if (pos > state.MAX_LEN - 1) {
611 memcpy(state.ptr + state.MAX_LEN, state.ptr1, state.MAX_LEN);
612 state.ptr[2 * state.MAX_LEN - 1] = '\0';
613 } else {
614 memcpy(state.ptr + state.MAX_LEN, state.ptr1, pos + 1);
615 }
616
617 ASSERT_EQ(strlcpy(state.ptr2, state.ptr1, state.MAX_LEN), strlen(state.ptr1));
618 ASSERT_FALSE((memcmp(state.ptr1, state.ptr, state.MAX_LEN) != 0) ||
619 (memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN) != 0));
620 }
Christopher Ferris14687652014-11-10 13:58:17 -0800621#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800622 GTEST_SKIP() << "strlcpy not available";
Christopher Ferris14687652014-11-10 13:58:17 -0800623#endif
Anna Tikhonova036154b2012-10-05 15:21:11 +0400624}
Anna Tikhonova036154b2012-10-05 15:21:11 +0400625
Christopher Ferris13f26a72016-01-13 13:47:58 -0800626TEST(STRING_TEST, strncat) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400627 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400628 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700629 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400630 memset(state.ptr2, '\2', state.MAX_LEN);
631 state.ptr2[state.MAX_LEN - 1] = '\0';
632 memcpy(state.ptr, state.ptr2, 2 * state.MAX_LEN);
633
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700634 memset(state.ptr1, 'I', state.len[i]);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400635 state.ptr1[random() % state.len[i]] = '\0';
636 state.ptr1[state.len[i] - 1] = '\0';
637
638 size_t pos = strlen(state.ptr1);
639
640 size_t actual = random() % state.len[i];
641 strncpy(state.ptr + state.MAX_LEN - 1, state.ptr1, std::min(actual, pos));
642 state.ptr[state.MAX_LEN + std::min(actual, pos) - 1] = '\0';
643
644 ASSERT_TRUE(strncat(state.ptr2, state.ptr1, actual) == state.ptr2);
645 ASSERT_EQ(memcmp(state.ptr, state.ptr2, 2 * state.MAX_LEN), 0);
646 }
647 }
648}
649
Christopher Ferris13f26a72016-01-13 13:47:58 -0800650TEST(STRING_TEST, strncmp) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400651 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400652 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700653 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400654 memset(state.ptr1, 'v', state.MAX_LEN);
655 memset(state.ptr2, 'n', state.MAX_LEN);
656 state.ptr1[state.len[i] - 1] = '\0';
657 state.ptr2[state.len[i] - 1] = '\0';
658
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700659 size_t pos = 1 + (random() % (state.MAX_LEN - 1));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400660 int actual;
661 int expected;
662 if (pos >= state.len[i] - 1) {
663 memcpy(state.ptr1, state.ptr2, state.len[i]);
664 expected = 0;
665 actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
666 } else {
667 memcpy(state.ptr1, state.ptr2, pos);
668 if (state.ptr1[pos] > state.ptr2[pos]) {
669 expected = 1;
670 } else if (state.ptr1[pos] == state.ptr2[pos]) {
671 state.ptr1[pos + 1] = '\0';
672 state.ptr2[pos + 1] = '\0';
673 expected = 0;
674 } else {
675 expected = -1;
676 }
677 actual = strncmp(state.ptr1, state.ptr2, state.len[i]);
678 }
679
680 ASSERT_EQ(expected, signum(actual));
681 }
682 }
683}
684
Christopher Ferris13f26a72016-01-13 13:47:58 -0800685TEST(STRING_TEST, stpncpy) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700686 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700687 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
688 memset(state.ptr1, 'J', state.MAX_LEN);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700689 // Choose a random size for our src buffer.
690 size_t ptr1_len = random() % state.MAX_LEN;
691 state.ptr1[ptr1_len] = '\0';
692 // Copy ptr1 into ptr, used to verify that ptr1 does not get modified.
693 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
694 // Init ptr2 to a set value.
695 memset(state.ptr2, '\1', state.MAX_LEN);
696
697 // Choose a random amount of data to copy.
698 size_t copy_len = random() % state.MAX_LEN;
699
700 // Set the second half of ptr to the expected pattern in ptr2.
701 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
702 memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len);
703 size_t expected_end;
704 if (copy_len > ptr1_len) {
705 memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len);
706 expected_end = ptr1_len;
707 } else {
708 expected_end = copy_len;
709 }
710
711 ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len));
712
713 // Verify ptr1 was not modified.
714 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN));
715 // Verify ptr2 contains the expected data.
716 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN));
717 }
718}
719
Christopher Ferris13f26a72016-01-13 13:47:58 -0800720TEST(STRING_TEST, strncpy) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400721 StringTestState<char> state(SMALL);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700722 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700723 // Choose a random value to fill the string, except \0 (string terminator),
724 // or \1 (guarantees it's different from anything in ptr2).
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700725 memset(state.ptr1, 'K', state.MAX_LEN);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700726 // Choose a random size for our src buffer.
727 size_t ptr1_len = random() % state.MAX_LEN;
728 state.ptr1[ptr1_len] = '\0';
729 // Copy ptr1 into ptr, used to verify that ptr1 does not get modified.
Anna Tikhonova036154b2012-10-05 15:21:11 +0400730 memcpy(state.ptr, state.ptr1, state.MAX_LEN);
Christopher Ferris950a58e2014-04-04 14:38:18 -0700731 // Init ptr2 to a set value.
Anna Tikhonova036154b2012-10-05 15:21:11 +0400732 memset(state.ptr2, '\1', state.MAX_LEN);
733
Christopher Ferris950a58e2014-04-04 14:38:18 -0700734 // Choose a random amount of data to copy.
735 size_t copy_len = random() % state.MAX_LEN;
736
737 // Set the second half of ptr to the expected pattern in ptr2.
738 memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
739 memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len);
740 size_t expected_end;
741 if (copy_len > ptr1_len) {
742 memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len);
743 expected_end = ptr1_len;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400744 } else {
Christopher Ferris950a58e2014-04-04 14:38:18 -0700745 expected_end = copy_len;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400746 }
747
Christopher Ferris950a58e2014-04-04 14:38:18 -0700748 ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400749
Christopher Ferris950a58e2014-04-04 14:38:18 -0700750 // Verify ptr1 was not modified.
751 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN));
752 // Verify ptr2 contains the expected data.
753 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr + state.MAX_LEN, state.MAX_LEN));
Anna Tikhonova036154b2012-10-05 15:21:11 +0400754 }
755}
756
Christopher Ferris13f26a72016-01-13 13:47:58 -0800757TEST(STRING_TEST, strrchr) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700758 int seek_char = 'M';
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400759 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400760 for (size_t i = 1; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700761 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400762 if (~seek_char > 0) {
763 memset(state.ptr1, ~seek_char, state.len[i]);
764 } else {
765 memset(state.ptr1, '\1', state.len[i]);
766 }
767 state.ptr1[state.len[i] - 1] = '\0';
768
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700769 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400770 char* expected;
771 if (pos >= state.len[i] - 1) {
772 if (seek_char == 0) {
773 expected = state.ptr1 + state.len[i] - 1;
774 } else {
Yi Kong32bc0fc2018-08-02 17:31:13 -0700775 expected = nullptr;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400776 }
777 } else {
778 state.ptr1[pos] = seek_char;
779 expected = state.ptr1 + pos;
780 }
781
782 ASSERT_TRUE(strrchr(state.ptr1, seek_char) == expected);
783 }
784 }
785}
786
Christopher Ferris13f26a72016-01-13 13:47:58 -0800787TEST(STRING_TEST, memchr) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700788 int seek_char = 'N';
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400789 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400790 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700791 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400792 memset(state.ptr1, ~seek_char, state.len[i]);
793
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700794 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400795 char* expected;
796 if (pos >= state.len[i]) {
Yi Kong32bc0fc2018-08-02 17:31:13 -0700797 expected = nullptr;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400798 } else {
799 state.ptr1[pos] = seek_char;
800 expected = state.ptr1 + pos;
801 }
802
803 ASSERT_TRUE(memchr(state.ptr1, seek_char, state.len[i]) == expected);
804 }
805 }
806}
807
Christopher Ferris13f26a72016-01-13 13:47:58 -0800808TEST(STRING_TEST, memchr_zero) {
Christopher Ferrise03e1ea2014-07-30 16:06:56 -0700809 uint8_t* buffer;
810 ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&buffer), 64, 64));
811 memset(buffer, 10, 64);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700812 ASSERT_TRUE(nullptr == memchr(buffer, 5, 0));
813 ASSERT_TRUE(nullptr == memchr(buffer, 10, 0));
Christopher Ferrise03e1ea2014-07-30 16:06:56 -0700814}
815
Christopher Ferris13f26a72016-01-13 13:47:58 -0800816TEST(STRING_TEST, memrchr) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700817 int seek_char = 'P';
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400818 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400819 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700820 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400821 memset(state.ptr1, ~seek_char, state.len[i]);
822
Dmitriy Ivanov7b956ed2014-09-04 12:47:07 -0700823 size_t pos = random() % state.MAX_LEN;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400824 char* expected;
825 if (pos >= state.len[i]) {
Yi Kong32bc0fc2018-08-02 17:31:13 -0700826 expected = nullptr;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400827 } else {
828 state.ptr1[pos] = seek_char;
829 expected = state.ptr1 + pos;
830 }
831
832 ASSERT_TRUE(memrchr(state.ptr1, seek_char, state.len[i]) == expected);
833 }
834 }
835}
836
Christopher Ferris13f26a72016-01-13 13:47:58 -0800837TEST(STRING_TEST, memcmp) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400838 StringTestState<char> state(SMALL);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400839 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700840 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
841 int c1 = 'A';
842 int c2 = 'N';
Anna Tikhonova036154b2012-10-05 15:21:11 +0400843 memset(state.ptr1, c1, state.MAX_LEN);
844 memset(state.ptr2, c1, state.MAX_LEN);
845
846 int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]);
847 state.ptr2[pos] = c2;
848
849 int expected = (static_cast<int>(c1) - static_cast<int>(c2));
850 int actual = memcmp(state.ptr1, state.ptr2, state.MAX_LEN);
851
852 ASSERT_EQ(signum(expected), signum(actual));
853 }
854 }
855}
856
Christopher Ferris13f26a72016-01-13 13:47:58 -0800857TEST(STRING_TEST, wmemcmp) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400858 StringTestState<wchar_t> state(SMALL);
859
860 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700861 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400862 long long mask = ((long long) 1 << 8 * sizeof(wchar_t)) - 1;
863 int c1 = rand() & mask;
864 int c2 = rand() & mask;
865 wmemset(state.ptr1, c1, state.MAX_LEN);
866 wmemset(state.ptr2, c1, state.MAX_LEN);
867
868 int pos = (state.len[i] == 0) ? 0 : (random() % state.len[i]);
869 state.ptr2[pos] = c2;
870
871 int expected = (static_cast<int>(c1) - static_cast<int>(c2));
872 int actual = wmemcmp(state.ptr1, state.ptr2, (size_t) state.MAX_LEN);
873
874 ASSERT_EQ(signum(expected), signum(actual));
875 }
876 }
877}
878
Christopher Ferris13f26a72016-01-13 13:47:58 -0800879TEST(STRING_TEST, memcpy) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400880 StringTestState<char> state(LARGE);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700881 int rand = 4;
Anna Tikhonova036154b2012-10-05 15:21:11 +0400882 for (size_t i = 0; i < state.n - 1; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700883 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400884 size_t pos = random() % (state.MAX_LEN - state.len[i]);
885
886 memset(state.ptr1, rand, state.len[i]);
887 memset(state.ptr1 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
888
889 memset(state.ptr2, rand, state.len[i]);
890 memset(state.ptr2 + state.len[i], ~rand, state.MAX_LEN - state.len[i]);
891 memset(state.ptr2 + pos, '\0', state.len[i]);
892
893 ASSERT_FALSE(memcpy(state.ptr2 + pos, state.ptr1 + pos, state.len[i]) != state.ptr2 + pos);
894 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
895 }
896 }
897}
898
Christopher Ferris13f26a72016-01-13 13:47:58 -0800899TEST(STRING_TEST, memset) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400900 StringTestState<char> state(LARGE);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700901 char ch = 'P';
Anna Tikhonova036154b2012-10-05 15:21:11 +0400902 for (size_t i = 0; i < state.n - 1; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700903 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
Anna Tikhonova036154b2012-10-05 15:21:11 +0400904 memset(state.ptr1, ~ch, state.MAX_LEN);
905 memcpy(state.ptr2, state.ptr1, state.MAX_LEN);
906
907 size_t pos = random () % (state.MAX_LEN - state.len[i]);
908 for (size_t k = pos; k < pos + state.len[i]; k++) {
909 state.ptr1[k] = ch;
910 }
911
912 ASSERT_TRUE(memset(state.ptr2 + pos, ch, state.len[i]) == state.ptr2 + pos);
913
914 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
915 }
916 }
917}
918
Christopher Ferris13f26a72016-01-13 13:47:58 -0800919TEST(STRING_TEST, memmove) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +0400920 StringTestState<char> state(LARGE);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400921 for (size_t i = 0; i < state.n - 1; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700922 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
923 memset(state.ptr1, 'Q', 2 * state.MAX_LEN);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400924
925 size_t pos = random() % (state.MAX_LEN - state.len[i]);
926
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700927 memset(state.ptr1, 'R', state.len[i]);
Anna Tikhonova036154b2012-10-05 15:21:11 +0400928 memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
929 memcpy(state.ptr, state.ptr1, state.len[i]);
930 memcpy(state.ptr1 + pos, state.ptr, state.len[i]);
931
932 ASSERT_TRUE(memmove(state.ptr2 + pos, state.ptr2, state.len[i]) == state.ptr2 + pos);
933 ASSERT_EQ(0, memcmp(state.ptr2, state.ptr1, 2 * state.MAX_LEN));
934 }
935 }
936}
937
Christopher Ferris13f26a72016-01-13 13:47:58 -0800938TEST(STRING_TEST, memmove_cache_size) {
Varvara Rainchikfce86142014-05-27 12:41:55 +0400939 size_t len = 600000;
940 int max_alignment = 31;
941 int alignments[] = {0, 5, 11, 29, 30};
942 char* ptr = reinterpret_cast<char*>(malloc(sizeof(char) * len));
943 char* ptr1 = reinterpret_cast<char*>(malloc(2 * sizeof(char) * len));
944 char* glob_ptr2 = reinterpret_cast<char*>(malloc(2 * sizeof(char) * len + max_alignment));
945 size_t pos = 64;
946
Yi Kong32bc0fc2018-08-02 17:31:13 -0700947 ASSERT_TRUE(ptr != nullptr);
948 ASSERT_TRUE(ptr1 != nullptr);
949 ASSERT_TRUE(glob_ptr2 != nullptr);
Varvara Rainchikfce86142014-05-27 12:41:55 +0400950
951 for (int i = 0; i < 5; i++) {
952 char* ptr2 = glob_ptr2 + alignments[i];
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -0700953 memset(ptr1, 'S', 2 * len);
954 memset(ptr1, 'T', len);
Varvara Rainchikfce86142014-05-27 12:41:55 +0400955 memcpy(ptr2, ptr1, 2 * len);
956 memcpy(ptr, ptr1, len);
957 memcpy(ptr1 + pos, ptr, len);
958
959 ASSERT_TRUE(memmove(ptr2 + pos, ptr, len) == ptr2 + pos);
960 ASSERT_EQ(0, memcmp(ptr2, ptr1, 2 * len));
961 }
962 free(ptr);
963 free(ptr1);
964 free(glob_ptr2);
965}
966
Shu Zhang6c80ccd2014-05-12 18:12:15 +0800967static void verify_memmove(char* src_copy, char* dst, char* src, size_t size) {
968 memset(dst, 0, size);
969 memcpy(src, src_copy, size);
970 ASSERT_EQ(dst, memmove(dst, src, size));
971 ASSERT_EQ(0, memcmp(dst, src_copy, size));
972}
973
974#define MEMMOVE_DATA_SIZE (1024*1024*3)
975
Christopher Ferris13f26a72016-01-13 13:47:58 -0800976TEST(STRING_TEST, memmove_check) {
Shu Zhang6c80ccd2014-05-12 18:12:15 +0800977 char* buffer = reinterpret_cast<char*>(malloc(MEMMOVE_DATA_SIZE));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700978 ASSERT_TRUE(buffer != nullptr);
Shu Zhang6c80ccd2014-05-12 18:12:15 +0800979
980 char* src_data = reinterpret_cast<char*>(malloc(MEMMOVE_DATA_SIZE));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700981 ASSERT_TRUE(src_data != nullptr);
Shu Zhang6c80ccd2014-05-12 18:12:15 +0800982 // Initialize to a known pattern to copy into src for each test and
983 // to compare dst against.
984 for (size_t i = 0; i < MEMMOVE_DATA_SIZE; i++) {
985 src_data[i] = (i + 1) % 255;
986 }
987
988 // Check all different dst offsets between 0 and 127 inclusive.
989 char* src = buffer;
990 for (size_t i = 0; i < 127; i++) {
991 char* dst = buffer + 256 + i;
992 // Small copy.
993 verify_memmove(src_data, dst, src, 1024);
994
995 // Medium copy.
996 verify_memmove(src_data, dst, src, 64 * 1024);
997
998 // Medium copy.
999 verify_memmove(src_data, dst, src, 1024 * 1024 + 128 * 1024);
1000 }
1001
1002 // Check all leftover size offsets between 1 and 127 inclusive.
1003 char* dst = buffer + 256;
1004 src = buffer;
1005 for (size_t size = 1; size < 127; size++) {
1006 // Small copy.
1007 verify_memmove(src_data, dst, src, 1024);
1008
1009 // Medium copy.
1010 verify_memmove(src_data, dst, src, 64 * 1024);
1011
1012 // Large copy.
1013 verify_memmove(src_data, dst, src, 1024 * 1024 + 128 * 1024);
1014 }
1015}
1016
Christopher Ferris13f26a72016-01-13 13:47:58 -08001017TEST(STRING_TEST, bcopy) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +04001018 StringTestState<char> state(LARGE);
Anna Tikhonova036154b2012-10-05 15:21:11 +04001019 for (size_t i = 0; i < state.n; i++) {
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -07001020 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
1021 memset(state.ptr1, '4', state.MAX_LEN);
1022 memset(state.ptr1 + state.MAX_LEN, 'a', state.MAX_LEN);
Anna Tikhonova036154b2012-10-05 15:21:11 +04001023 memcpy(state.ptr2, state.ptr1, 2 * state.MAX_LEN);
1024
1025 size_t start = random() % (2 * state.MAX_LEN - state.len[i]);
1026 memcpy(state.ptr2 + start, state.ptr1, state.len[i]);
1027
1028 bcopy(state.ptr1, state.ptr1 + start, state.len[i]);
1029 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, 2 * state.MAX_LEN));
1030 }
1031 }
1032}
1033
Christopher Ferris13f26a72016-01-13 13:47:58 -08001034TEST(STRING_TEST, bzero) {
Alexander Ivchenkobaa91f42013-06-27 12:55:46 +04001035 StringTestState<char> state(LARGE);
Dmitriy Ivanov1467dfe2014-08-13 11:24:37 -07001036 for (state.BeginIterations(); state.HasNextIteration(); state.NextIteration()) {
1037 memset(state.ptr1, 'R', state.MAX_LEN);
Anna Tikhonova036154b2012-10-05 15:21:11 +04001038
1039 size_t start = random() % state.MAX_LEN;
1040 size_t end = start + random() % (state.MAX_LEN - start);
1041
1042 memcpy(state.ptr2, state.ptr1, start);
1043 memset(state.ptr2 + start, '\0', end - start);
1044 memcpy(state.ptr2 + end, state.ptr1 + end, state.MAX_LEN - end);
1045
1046 bzero(state.ptr1 + start, end - start);
1047
1048 ASSERT_EQ(0, memcmp(state.ptr1, state.ptr2, state.MAX_LEN));
1049 }
1050}
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001051
1052static void DoMemcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1053 memset(src, (len % 255) + 1, len);
1054 memset(dst, 0, len);
1055
1056 ASSERT_EQ(dst, memcpy(dst, src, len));
1057 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1058}
1059
Christopher Ferris13f26a72016-01-13 13:47:58 -08001060TEST(STRING_TEST, memcpy_align) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001061 RunSrcDstBufferAlignTest(LARGE, DoMemcpyTest);
1062}
1063
Christopher Ferris13f26a72016-01-13 13:47:58 -08001064TEST(STRING_TEST, memcpy_overread) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001065 RunSrcDstBufferOverreadTest(DoMemcpyTest);
1066}
1067
Shu Zhang6c80ccd2014-05-12 18:12:15 +08001068static void DoMemmoveTest(uint8_t* src, uint8_t* dst, size_t len) {
1069 memset(src, (len % 255) + 1, len);
1070 memset(dst, 0, len);
1071
1072 ASSERT_EQ(dst, memmove(dst, src, len));
1073 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1074}
1075
Christopher Ferris13f26a72016-01-13 13:47:58 -08001076TEST(STRING_TEST, memmove_align) {
Shu Zhang6c80ccd2014-05-12 18:12:15 +08001077 RunSrcDstBufferAlignTest(LARGE, DoMemmoveTest);
1078}
1079
Christopher Ferris13f26a72016-01-13 13:47:58 -08001080TEST(STRING_TEST, memmove_overread) {
Shu Zhang6c80ccd2014-05-12 18:12:15 +08001081 RunSrcDstBufferOverreadTest(DoMemmoveTest);
1082}
1083
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001084static void DoMemsetTest(uint8_t* buf, size_t len) {
1085 for (size_t i = 0; i < len; i++) {
1086 buf[i] = 0;
1087 }
1088 int value = (len % 255) + 1;
1089 ASSERT_EQ(buf, memset(buf, value, len));
1090 for (size_t i = 0; i < len; i++) {
1091 ASSERT_EQ(value, buf[i]);
1092 }
1093}
1094
Christopher Ferris13f26a72016-01-13 13:47:58 -08001095TEST(STRING_TEST, memset_align) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001096 RunSingleBufferAlignTest(LARGE, DoMemsetTest);
1097}
1098
1099static void DoStrlenTest(uint8_t* buf, size_t len) {
1100 if (len >= 1) {
1101 memset(buf, (32 + (len % 96)), len - 1);
1102 buf[len-1] = '\0';
1103 ASSERT_EQ(len-1, strlen(reinterpret_cast<char*>(buf)));
1104 }
1105}
1106
Christopher Ferris13f26a72016-01-13 13:47:58 -08001107TEST(STRING_TEST, strlen_align) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001108 RunSingleBufferAlignTest(LARGE, DoStrlenTest);
1109}
1110
Christopher Ferris13f26a72016-01-13 13:47:58 -08001111TEST(STRING_TEST, strlen_overread) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001112 RunSingleBufferOverreadTest(DoStrlenTest);
1113}
1114
1115static void DoStrcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1116 if (len >= 1) {
1117 memset(src, (32 + (len % 96)), len - 1);
1118 src[len-1] = '\0';
1119 memset(dst, 0, len);
1120 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcpy(reinterpret_cast<char*>(dst),
1121 reinterpret_cast<char*>(src))));
1122 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1123 }
1124}
1125
Christopher Ferris13f26a72016-01-13 13:47:58 -08001126TEST(STRING_TEST, strcpy_align) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001127 RunSrcDstBufferAlignTest(LARGE, DoStrcpyTest);
1128}
1129
Christopher Ferris13f26a72016-01-13 13:47:58 -08001130TEST(STRING_TEST, strcpy_overread) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001131 RunSrcDstBufferOverreadTest(DoStrcpyTest);
1132}
1133
Christopher Ferris14687652014-11-10 13:58:17 -08001134#if defined(STRLCPY_SUPPORTED)
1135static void DoStrlcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1136 if (len >= 1) {
1137 memset(src, (32 + (len % 96)), len - 1);
1138 src[len-1] = '\0';
1139 memset(dst, 0, len);
1140 ASSERT_EQ(len-1, strlcpy(reinterpret_cast<char*>(dst),
1141 reinterpret_cast<char*>(src), len));
1142 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1143 }
1144}
1145#endif
1146
Christopher Ferris13f26a72016-01-13 13:47:58 -08001147TEST(STRING_TEST, strlcpy_align) {
Christopher Ferris14687652014-11-10 13:58:17 -08001148#if defined(STRLCPY_SUPPORTED)
1149 RunSrcDstBufferAlignTest(LARGE, DoStrlcpyTest);
1150#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08001151 GTEST_SKIP() << "strlcpy not available";
Christopher Ferris14687652014-11-10 13:58:17 -08001152#endif
1153}
1154
Christopher Ferris13f26a72016-01-13 13:47:58 -08001155TEST(STRING_TEST, strlcpy_overread) {
Christopher Ferris14687652014-11-10 13:58:17 -08001156#if defined(STRLCPY_SUPPORTED)
1157 RunSrcDstBufferOverreadTest(DoStrlcpyTest);
1158#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08001159 GTEST_SKIP() << "strlcpy not available";
Christopher Ferris14687652014-11-10 13:58:17 -08001160#endif
1161}
1162
1163
Christopher Ferris950a58e2014-04-04 14:38:18 -07001164static void DoStpcpyTest(uint8_t* src, uint8_t* dst, size_t len) {
1165 if (len >= 1) {
1166 memset(src, (32 + (len % 96)), len - 1);
1167 src[len-1] = '\0';
1168 memset(dst, 0, len);
1169 ASSERT_EQ(dst+len-1, reinterpret_cast<uint8_t*>(stpcpy(reinterpret_cast<char*>(dst),
1170 reinterpret_cast<char*>(src))));
1171 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1172 }
1173}
1174
Christopher Ferris13f26a72016-01-13 13:47:58 -08001175TEST(STRING_TEST, stpcpy_align) {
Christopher Ferris950a58e2014-04-04 14:38:18 -07001176 RunSrcDstBufferAlignTest(LARGE, DoStpcpyTest);
1177}
1178
Christopher Ferris13f26a72016-01-13 13:47:58 -08001179TEST(STRING_TEST, stpcpy_overread) {
Christopher Ferris950a58e2014-04-04 14:38:18 -07001180 RunSrcDstBufferOverreadTest(DoStpcpyTest);
1181}
1182
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001183// Use our own incrementer to cut down on the total number of calls.
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001184static size_t LargeSetIncrement(size_t len) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001185 if (len >= 4096) {
1186 return 4096;
1187 } else if (len >= 1024) {
1188 return 1024;
1189 } else if (len >= 256) {
1190 return 256;
1191 }
1192 return 1;
1193}
1194
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001195#define STRCAT_DST_LEN 64
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001196
1197static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) {
1198 if (len >= 1) {
1199 int value = 32 + (len % 96);
1200 memset(src, value, len - 1);
1201 src[len-1] = '\0';
1202
1203 if (len >= STRCAT_DST_LEN) {
1204 // Create a small buffer for doing quick compares in each loop.
1205 uint8_t cmp_buf[STRCAT_DST_LEN];
1206 // Make sure dst string contains a different value then the src string.
1207 int value2 = 32 + (value + 2) % 96;
1208 memset(cmp_buf, value2, sizeof(cmp_buf));
1209
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001210 for (size_t i = 1; i <= STRCAT_DST_LEN;) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001211 memset(dst, value2, i-1);
1212 memset(dst+i-1, 0, len-i);
1213 src[len-i] = '\0';
1214 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst),
1215 reinterpret_cast<char*>(src))));
1216 ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
1217 ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001218 // This is an expensive loop, so don't loop through every value,
1219 // get to a certain size and then start doubling.
1220 if (i < 16) {
1221 i++;
1222 } else {
1223 i <<= 1;
1224 }
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001225 }
1226 } else {
1227 dst[0] = '\0';
1228 ASSERT_EQ(dst, reinterpret_cast<uint8_t*>(strcat(reinterpret_cast<char*>(dst),
1229 reinterpret_cast<char*>(src))));
1230 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1231 }
1232 }
1233}
1234
Christopher Ferris13f26a72016-01-13 13:47:58 -08001235TEST(STRING_TEST, strcat_align) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001236 RunSrcDstBufferAlignTest(MEDIUM, DoStrcatTest, LargeSetIncrement);
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001237}
1238
Christopher Ferris13f26a72016-01-13 13:47:58 -08001239TEST(STRING_TEST, strcat_overread) {
Christopher Ferrisb687ad32013-11-06 17:32:11 -08001240 RunSrcDstBufferOverreadTest(DoStrcatTest);
1241}
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001242
Christopher Ferris14687652014-11-10 13:58:17 -08001243#if defined(STRLCAT_SUPPORTED)
1244static void DoStrlcatTest(uint8_t* src, uint8_t* dst, size_t len) {
1245 if (len >= 1) {
1246 int value = 32 + (len % 96);
1247 memset(src, value, len - 1);
1248 src[len-1] = '\0';
1249
1250 if (len >= STRCAT_DST_LEN) {
1251 // Create a small buffer for doing quick compares in each loop.
1252 uint8_t cmp_buf[STRCAT_DST_LEN];
1253 // Make sure dst string contains a different value then the src string.
1254 int value2 = 32 + (value + 2) % 96;
1255 memset(cmp_buf, value2, sizeof(cmp_buf));
1256
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001257 for (size_t i = 1; i <= STRCAT_DST_LEN;) {
Christopher Ferris14687652014-11-10 13:58:17 -08001258 memset(dst, value2, i-1);
1259 memset(dst+i-1, 0, len-i);
1260 src[len-i] = '\0';
1261 ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
1262 reinterpret_cast<char*>(src), len));
1263 ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
1264 ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
Christopher Ferrisfdfcfce2015-09-23 22:09:09 -07001265 // This is an expensive loop, so don't loop through every value,
1266 // get to a certain size and then start doubling.
1267 if (i < 16) {
1268 i++;
1269 } else {
1270 i <<= 1;
1271 }
Christopher Ferris14687652014-11-10 13:58:17 -08001272 }
1273 } else {
1274 dst[0] = '\0';
1275 ASSERT_EQ(len-1, strlcat(reinterpret_cast<char*>(dst),
1276 reinterpret_cast<char*>(src), len));
1277 ASSERT_TRUE(memcmp(src, dst, len) == 0);
1278 }
1279 }
1280}
1281#endif
1282
Christopher Ferris13f26a72016-01-13 13:47:58 -08001283TEST(STRING_TEST, strlcat_align) {
Christopher Ferris14687652014-11-10 13:58:17 -08001284#if defined(STRLCAT_SUPPORTED)
1285 RunSrcDstBufferAlignTest(MEDIUM, DoStrlcatTest, LargeSetIncrement);
1286#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08001287 GTEST_SKIP() << "strlcat not available";
Christopher Ferris14687652014-11-10 13:58:17 -08001288#endif
1289}
1290
Christopher Ferris13f26a72016-01-13 13:47:58 -08001291TEST(STRING_TEST, strlcat_overread) {
Christopher Ferris14687652014-11-10 13:58:17 -08001292#if defined(STRLCAT_SUPPORTED)
1293 RunSrcDstBufferOverreadTest(DoStrlcatTest);
1294#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08001295 GTEST_SKIP() << "strlcat not available";
Christopher Ferris14687652014-11-10 13:58:17 -08001296#endif
1297}
1298
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001299static void DoStrcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
1300 if (len >= 1) {
1301 memset(buf1, (32 + (len % 96)), len - 1);
1302 buf1[len-1] = '\0';
1303 memset(buf2, (32 + (len % 96)), len - 1);
1304 buf2[len-1] = '\0';
1305 ASSERT_EQ(0, strcmp(reinterpret_cast<char*>(buf1),
1306 reinterpret_cast<char*>(buf2)));
1307 }
1308}
1309
1310static void DoStrcmpFailTest(uint8_t* buf1, uint8_t* buf2, size_t len1, size_t len2) {
1311 // Do string length differences.
1312 int c = (32 + (len1 % 96));
1313 memset(buf1, c, len1 - 1);
1314 buf1[len1-1] = '\0';
1315 memset(buf2, c, len2 - 1);
1316 buf2[len2-1] = '\0';
1317 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1318 reinterpret_cast<char*>(buf2)));
1319
1320 // Do single character differences.
1321 size_t len;
1322 if (len1 > len2) {
1323 len = len2;
1324 } else {
1325 len = len1;
1326 }
1327 // Need at least a two character buffer to do this test.
1328 if (len > 1) {
1329 buf1[len-1] = '\0';
1330 buf2[len-1] = '\0';
1331 int diff_c = (c + 1) % 96;
1332
1333 buf1[len-2] = diff_c;
1334 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1335 reinterpret_cast<char*>(buf2)));
1336
1337 buf1[len-2] = c;
1338 buf2[len-2] = diff_c;
1339 ASSERT_NE(0, strcmp(reinterpret_cast<char*>(buf1),
1340 reinterpret_cast<char*>(buf2)));
1341 }
1342}
1343
Christopher Ferris13f26a72016-01-13 13:47:58 -08001344TEST(STRING_TEST, strcmp_align) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001345 RunCmpBufferAlignTest(MEDIUM, DoStrcmpTest, DoStrcmpFailTest, LargeSetIncrement);
1346}
1347
Christopher Ferris13f26a72016-01-13 13:47:58 -08001348TEST(STRING_TEST, strcmp_overread) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001349 RunCmpBufferOverreadTest(DoStrcmpTest, DoStrcmpFailTest);
1350}
1351
1352static void DoMemcmpTest(uint8_t* buf1, uint8_t* buf2, size_t len) {
1353 memset(buf1, len+1, len);
1354 memset(buf2, len+1, len);
1355 ASSERT_EQ(0, memcmp(buf1, buf2, len));
1356}
1357
1358static void DoMemcmpFailTest(uint8_t* buf1, uint8_t* buf2, size_t len1, size_t len2) {
1359 size_t len;
1360 if (len1 > len2) {
1361 len = len2;
1362 } else {
1363 len = len1;
1364 }
1365
1366 memset(buf1, len2+1, len);
1367 buf1[len-1] = len2;
1368 memset(buf2, len2+1, len);
1369 ASSERT_NE(0, memcmp(buf1, buf2, len));
1370
1371 buf1[len-1] = len2+1;
1372 buf2[len-1] = len2;
1373 ASSERT_NE(0, memcmp(buf1, buf2, len));
1374}
1375
Christopher Ferris13f26a72016-01-13 13:47:58 -08001376TEST(STRING_TEST, memcmp_align) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001377 RunCmpBufferAlignTest(MEDIUM, DoMemcmpTest, DoMemcmpFailTest, LargeSetIncrement);
1378}
1379
Christopher Ferris13f26a72016-01-13 13:47:58 -08001380TEST(STRING_TEST, memcmp_overread) {
Christopher Ferrise5bbb6b2013-12-03 18:39:10 -08001381 RunCmpBufferOverreadTest(DoMemcmpTest, DoMemcmpFailTest);
1382}
Christopher Ferris3a657d02014-06-27 12:33:22 -07001383
Christopher Ferris2f030af2017-05-08 14:24:29 -07001384static void DoMemchrTest(uint8_t* buf, size_t len) {
1385 if (len >= 1) {
1386 int value = len % 128;
1387 int search_value = (len % 128) + 1;
1388 memset(buf, value, len);
1389 // The buffer does not contain the search value.
1390 ASSERT_EQ(nullptr, memchr(buf, search_value, len));
1391 if (len >= 2) {
1392 buf[0] = search_value;
1393 // The search value is the first element in the buffer.
1394 ASSERT_EQ(&buf[0], memchr(buf, search_value, len));
1395
1396 buf[0] = value;
1397 buf[len - 1] = search_value;
1398 // The search value is the last element in the buffer.
1399 ASSERT_EQ(&buf[len - 1], memchr(buf, search_value, len));
1400 }
1401 }
1402}
1403
1404TEST(STRING_TEST, memchr_align) {
1405 RunSingleBufferAlignTest(MEDIUM, DoMemchrTest);
1406}
1407
1408TEST(STRING_TEST, memchr_overread) {
1409 RunSingleBufferOverreadTest(DoMemchrTest);
1410}
1411
Christopher Ferris3a657d02014-06-27 12:33:22 -07001412static void DoStrchrTest(uint8_t* buf, size_t len) {
1413 if (len >= 1) {
1414 char value = 32 + (len % 96);
1415 char search_value = 33 + (len % 96);
1416 memset(buf, value, len - 1);
Christopher Ferris2f030af2017-05-08 14:24:29 -07001417 buf[len - 1] = '\0';
1418 // The buffer does not contain the search value.
1419 ASSERT_EQ(nullptr, strchr(reinterpret_cast<char*>(buf), search_value));
1420 // Search for the special '\0' character.
1421 ASSERT_EQ(reinterpret_cast<char*>(&buf[len - 1]), strchr(reinterpret_cast<char*>(buf), '\0'));
Christopher Ferris3a657d02014-06-27 12:33:22 -07001422 if (len >= 2) {
1423 buf[0] = search_value;
Christopher Ferris2f030af2017-05-08 14:24:29 -07001424 // The search value is the first element in the buffer.
1425 ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strchr(reinterpret_cast<char*>(buf),
1426 search_value));
1427
Christopher Ferris3a657d02014-06-27 12:33:22 -07001428 buf[0] = value;
Christopher Ferris2f030af2017-05-08 14:24:29 -07001429 buf[len - 2] = search_value;
1430 // The search value is the second to last element in the buffer.
1431 // The last element is the '\0' character.
1432 ASSERT_EQ(reinterpret_cast<char*>(&buf[len - 2]), strchr(reinterpret_cast<char*>(buf),
1433 search_value));
Christopher Ferris3a657d02014-06-27 12:33:22 -07001434 }
1435 }
1436}
1437
Christopher Ferris13f26a72016-01-13 13:47:58 -08001438TEST(STRING_TEST, strchr_align) {
Christopher Ferris3a657d02014-06-27 12:33:22 -07001439 RunSingleBufferAlignTest(MEDIUM, DoStrchrTest);
1440}
1441
Christopher Ferris13f26a72016-01-13 13:47:58 -08001442TEST(STRING_TEST, strchr_overread) {
Christopher Ferris3a657d02014-06-27 12:33:22 -07001443 RunSingleBufferOverreadTest(DoStrchrTest);
1444}
Elliott Hughes09c39d62014-08-19 14:30:30 -07001445
Christopher Ferris2f030af2017-05-08 14:24:29 -07001446static void DoStrrchrTest(uint8_t* buf, size_t len) {
1447 if (len >= 1) {
1448 char value = 32 + (len % 96);
1449 char search_value = 33 + (len % 96);
1450 memset(buf, value, len - 1);
1451 buf[len - 1] = '\0';
1452 // The buffer does not contain the search value.
1453 ASSERT_EQ(nullptr, strrchr(reinterpret_cast<char*>(buf), search_value));
1454 // Search for the special '\0' character.
1455 ASSERT_EQ(reinterpret_cast<char*>(&buf[len - 1]), strrchr(reinterpret_cast<char*>(buf), '\0'));
1456 if (len >= 2) {
1457 buf[0] = search_value;
1458 // The search value is the first element in the buffer.
1459 ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strrchr(reinterpret_cast<char*>(buf),
1460 search_value));
1461
1462 buf[0] = value;
1463 buf[len - 2] = search_value;
1464 // The search value is the second to last element in the buffer.
1465 // The last element is the '\0' character.
1466 ASSERT_EQ(reinterpret_cast<char*>(&buf[len - 2]), strrchr(reinterpret_cast<char*>(buf),
1467 search_value));
1468 }
1469 }
1470}
1471
1472TEST(STRING_TEST, strrchr_align) {
1473 RunSingleBufferAlignTest(MEDIUM, DoStrrchrTest);
1474}
1475
1476TEST(STRING_TEST, strrchr_overread) {
1477 RunSingleBufferOverreadTest(DoStrrchrTest);
1478}
1479
Colin Cross7da20342021-07-28 11:18:11 -07001480#if !defined(MUSL)
Elliott Hughes09c39d62014-08-19 14:30:30 -07001481static void TestBasename(const char* in, const char* expected_out) {
1482 errno = 0;
1483 const char* out = basename(in);
1484 ASSERT_STREQ(expected_out, out) << in;
1485 ASSERT_EQ(0, errno) << in;
1486}
Colin Cross7da20342021-07-28 11:18:11 -07001487#endif
Elliott Hughes09c39d62014-08-19 14:30:30 -07001488
Christopher Ferris13f26a72016-01-13 13:47:58 -08001489TEST(STRING_TEST, __gnu_basename) {
Colin Cross7da20342021-07-28 11:18:11 -07001490#if !defined(MUSL)
Elliott Hughes09c39d62014-08-19 14:30:30 -07001491 TestBasename("", "");
1492 TestBasename("/usr/lib", "lib");
1493 TestBasename("/usr/", "");
1494 TestBasename("usr", "usr");
1495 TestBasename("/", "");
1496 TestBasename(".", ".");
1497 TestBasename("..", "..");
1498 TestBasename("///", "");
1499 TestBasename("//usr//lib//", "");
Colin Cross7da20342021-07-28 11:18:11 -07001500#else
1501 GTEST_SKIP() << "musl doesn't have GNU basename";
1502#endif
Elliott Hughes09c39d62014-08-19 14:30:30 -07001503}
Elliott Hughes41ef9022015-02-14 13:21:22 -08001504
Christopher Ferris13f26a72016-01-13 13:47:58 -08001505TEST(STRING_TEST, strnlen_147048) {
Elliott Hughes41ef9022015-02-14 13:21:22 -08001506 // https://code.google.com/p/android/issues/detail?id=147048
1507 char stack_src[64] = {0};
1508 EXPECT_EQ(0U, strnlen(stack_src, 1024*1024*1024));
1509 char* heap_src = new char[1];
1510 *heap_src = '\0';
1511 EXPECT_EQ(0U, strnlen(heap_src, 1024*1024*1024));
1512 delete[] heap_src;
1513}
Elliott Hughes3cfb52a2015-02-18 21:29:13 -08001514
Christopher Ferris13f26a72016-01-13 13:47:58 -08001515TEST(STRING_TEST, strnlen_74741) {
Elliott Hughesd2a9fb32015-07-27 20:55:03 -07001516 ASSERT_EQ(4U, strnlen("test", SIZE_MAX));
1517}
1518
Christopher Ferris13f26a72016-01-13 13:47:58 -08001519TEST(STRING_TEST, mempcpy) {
Elliott Hughes3cfb52a2015-02-18 21:29:13 -08001520 char dst[6];
1521 ASSERT_EQ(&dst[4], reinterpret_cast<char*>(mempcpy(dst, "hello", 4)));
1522}
Christopher Ferris71766c22016-02-12 17:24:27 -08001523
1524// clang depends on the fact that a memcpy where src and dst is the same
1525// still operates correctly. This test verifies that this assumption
1526// holds true.
1527// See https://llvm.org/bugs/show_bug.cgi?id=11763 for more information.
1528static std::vector<uint8_t> g_memcpy_same_buffer;
1529
1530static void DoMemcpySameTest(uint8_t* buffer, size_t len) {
1531 memcpy(buffer, g_memcpy_same_buffer.data(), len);
1532 ASSERT_EQ(buffer, memcpy(buffer, buffer, len));
1533 ASSERT_TRUE(memcmp(buffer, g_memcpy_same_buffer.data(), len) == 0);
1534}
1535
1536TEST(STRING_TEST, memcpy_src_dst_same) {
1537 g_memcpy_same_buffer.resize(MEDIUM);
1538 for (size_t i = 0; i < MEDIUM; i++) {
1539 g_memcpy_same_buffer[i] = i;
1540 }
1541 RunSingleBufferAlignTest(MEDIUM, DoMemcpySameTest);
1542}
Elliott Hughescae33ad2016-08-15 14:14:40 -07001543
1544TEST(STRING_TEST, memmem_strstr_empty_needle) {
1545 const char* some_haystack = "haystack";
1546 const char* empty_haystack = "";
1547
1548 ASSERT_EQ(some_haystack, memmem(some_haystack, 8, "", 0));
1549 ASSERT_EQ(empty_haystack, memmem(empty_haystack, 0, "", 0));
1550
1551 ASSERT_EQ(some_haystack, strstr(some_haystack, ""));
1552 ASSERT_EQ(empty_haystack, strstr(empty_haystack, ""));
1553}
1554
1555TEST(STRING_TEST, memmem_smoke) {
Elliott Hughes5633caa2020-08-06 14:32:43 -07001556 const char haystack[] = "big\0daddy/giant\0haystacks!";
1557
1558 // The current memmem() implementation has special cases for needles of
1559 // lengths 0, 1, 2, 3, and 4, plus a long needle case. We test matches at the
1560 // beginning, middle, and end of the haystack.
1561
1562 ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "", 0));
1563
Elliott Hughescae33ad2016-08-15 14:14:40 -07001564 ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "b", 1));
Elliott Hughes5633caa2020-08-06 14:32:43 -07001565 ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "bi", 2));
1566 ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "big", 3));
1567 ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "big\0", 4));
1568 ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "big\0d", 5));
1569
1570 ASSERT_EQ(haystack + 2, memmem(haystack, sizeof(haystack), "g", 1));
1571 ASSERT_EQ(haystack + 10, memmem(haystack, sizeof(haystack), "gi", 2));
1572 ASSERT_EQ(haystack + 10, memmem(haystack, sizeof(haystack), "gia", 3));
1573 ASSERT_EQ(haystack + 10, memmem(haystack, sizeof(haystack), "gian", 4));
1574 ASSERT_EQ(haystack + 10, memmem(haystack, sizeof(haystack), "giant", 5));
1575
1576 ASSERT_EQ(haystack + 25, memmem(haystack, sizeof(haystack), "!", 1));
1577 ASSERT_EQ(haystack + 24, memmem(haystack, sizeof(haystack), "s!", 2));
1578 ASSERT_EQ(haystack + 23, memmem(haystack, sizeof(haystack), "ks!", 3));
1579 ASSERT_EQ(haystack + 22, memmem(haystack, sizeof(haystack), "cks!", 4));
1580 ASSERT_EQ(haystack + 21, memmem(haystack, sizeof(haystack), "acks!", 5));
Elliott Hughescae33ad2016-08-15 14:14:40 -07001581}
1582
1583TEST(STRING_TEST, strstr_smoke) {
Elliott Hughesc6b38ae2019-11-22 11:15:42 -08001584 const char* haystack = "big daddy/giant haystacks!";
1585
1586 // The current strstr() implementation has special cases for needles of
1587 // lengths 0, 1, 2, 3, and 4, plus a long needle case. We test matches at the
1588 // beginning, middle, and end of the haystack.
1589
1590 ASSERT_EQ(haystack + 0, strstr(haystack, ""));
1591
Elliott Hughescae33ad2016-08-15 14:14:40 -07001592 ASSERT_EQ(haystack + 0, strstr(haystack, "b"));
Elliott Hughesc6b38ae2019-11-22 11:15:42 -08001593 ASSERT_EQ(haystack + 0, strstr(haystack, "bi"));
1594 ASSERT_EQ(haystack + 0, strstr(haystack, "big"));
1595 ASSERT_EQ(haystack + 0, strstr(haystack, "big "));
1596 ASSERT_EQ(haystack + 0, strstr(haystack, "big d"));
1597
1598 ASSERT_EQ(haystack + 2, strstr(haystack, "g"));
1599 ASSERT_EQ(haystack + 10, strstr(haystack, "gi"));
1600 ASSERT_EQ(haystack + 10, strstr(haystack, "gia"));
1601 ASSERT_EQ(haystack + 10, strstr(haystack, "gian"));
1602 ASSERT_EQ(haystack + 10, strstr(haystack, "giant"));
1603
1604 ASSERT_EQ(haystack + 25, strstr(haystack, "!"));
1605 ASSERT_EQ(haystack + 24, strstr(haystack, "s!"));
1606 ASSERT_EQ(haystack + 23, strstr(haystack, "ks!"));
1607 ASSERT_EQ(haystack + 22, strstr(haystack, "cks!"));
1608 ASSERT_EQ(haystack + 21, strstr(haystack, "acks!"));
Elliott Hughescae33ad2016-08-15 14:14:40 -07001609}
Elliott Hughesfbac97a2019-02-04 16:46:24 -08001610
1611TEST(STRING_TEST, strcasestr_smoke) {
1612 const char* haystack = "bIg dAdDy/gIaNt hAyStAcKs";
1613 ASSERT_EQ(haystack, strcasestr(haystack, ""));
1614 ASSERT_EQ(haystack + 0, strcasestr(haystack, "B"));
1615 ASSERT_EQ(haystack + 1, strcasestr(haystack, "i"));
1616 ASSERT_EQ(haystack + 4, strcasestr(haystack, "Da"));
1617}
1618
1619TEST(STRING_TEST, strcoll_smoke) {
1620 ASSERT_TRUE(strcoll("aab", "aac") < 0);
1621 ASSERT_TRUE(strcoll("aab", "aab") == 0);
1622 ASSERT_TRUE(strcoll("aac", "aab") > 0);
1623}
1624
Elliott Hughes7cebf832020-08-12 14:25:41 -07001625TEST(STRING_TEST, strcoll_l_smoke) {
1626 // bionic just forwards to strcoll(3).
1627 ASSERT_TRUE(strcoll_l("aab", "aac", LC_GLOBAL_LOCALE) < 0);
1628 ASSERT_TRUE(strcoll_l("aab", "aab", LC_GLOBAL_LOCALE) == 0);
1629 ASSERT_TRUE(strcoll_l("aac", "aab", LC_GLOBAL_LOCALE) > 0);
1630}
1631
Elliott Hughesfbac97a2019-02-04 16:46:24 -08001632TEST(STRING_TEST, strxfrm_smoke) {
1633 const char* src1 = "aab";
1634 char dst1[16] = {};
Elliott Hughes2e71c172020-08-06 13:53:40 -07001635 // Dry run.
1636 ASSERT_EQ(strxfrm(dst1, src1, 0), 3U);
1637 ASSERT_STREQ(dst1, "");
1638 // Really do it.
1639 ASSERT_EQ(strxfrm(dst1, src1, sizeof(dst1)), 3U);
1640
Elliott Hughesfbac97a2019-02-04 16:46:24 -08001641 const char* src2 = "aac";
1642 char dst2[16] = {};
Elliott Hughes2e71c172020-08-06 13:53:40 -07001643 // Dry run.
1644 ASSERT_EQ(strxfrm(dst2, src2, 0), 3U);
1645 ASSERT_STREQ(dst2, "");
1646 // Really do it.
1647 ASSERT_EQ(strxfrm(dst2, src2, sizeof(dst2)), 3U);
1648
1649 // The "transform" of two different strings should cause different outputs.
Elliott Hughesfbac97a2019-02-04 16:46:24 -08001650 ASSERT_TRUE(strcmp(dst1, dst2) < 0);
1651}
1652
Elliott Hughes7cebf832020-08-12 14:25:41 -07001653TEST(STRING_TEST, strxfrm_l_smoke) {
1654 // bionic just forwards to strxfrm(3), so this is a subset of the
1655 // strxfrm test.
1656 const char* src1 = "aab";
1657 char dst1[16] = {};
1658 ASSERT_EQ(strxfrm_l(dst1, src1, 0, LC_GLOBAL_LOCALE), 3U);
1659 ASSERT_STREQ(dst1, "");
1660 ASSERT_EQ(strxfrm_l(dst1, src1, sizeof(dst1), LC_GLOBAL_LOCALE), 3U);
1661}
1662
Elliott Hughesfbac97a2019-02-04 16:46:24 -08001663TEST(STRING_TEST, memccpy_smoke) {
1664 char dst[32];
1665
1666 memset(dst, 0, sizeof(dst));
1667 char* p = static_cast<char*>(memccpy(dst, "hello world", ' ', 32));
1668 ASSERT_STREQ("hello ", dst);
1669 ASSERT_EQ(ptrdiff_t(6), p - dst);
1670
1671 memset(dst, 0, sizeof(dst));
1672 ASSERT_EQ(nullptr, memccpy(dst, "hello world", ' ', 4));
1673 ASSERT_STREQ("hell", dst);
1674}