blob: c20597b37bec5bb24b07925067503ad82dfbebf4 [file] [log] [blame]
Elliott Hughes91875dc2012-09-24 17:55:15 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
19#include <errno.h>
Elliott Hughesc9244bd2014-05-14 13:31:35 -070020#include <fcntl.h>
Elliott Hughes1d13c642013-09-23 16:02:39 -070021#include <limits.h>
Colin Cross14d15072021-08-16 16:35:27 -070022#include <locale.h>
Elliott Hughes7823f322014-04-14 12:11:28 -070023#include <math.h>
Elliott Hughes91875dc2012-09-24 17:55:15 -070024#include <stdio.h>
Colin Cross4c5595c2021-08-16 15:51:59 -070025#include <sys/cdefs.h>
Elliott Hughes468efc82018-07-10 14:39:49 -070026#include <sys/socket.h>
Elliott Hughes91875dc2012-09-24 17:55:15 -070027#include <sys/stat.h>
Elliott Hughesbe78fc92022-07-28 20:58:45 +000028#include <sys/sysinfo.h>
Colin Cross14d15072021-08-16 16:35:27 -070029#include <sys/types.h>
Elliott Hughes91875dc2012-09-24 17:55:15 -070030#include <unistd.h>
Elliott Hughes05493712014-04-17 17:30:03 -070031#include <wchar.h>
Calin Juravle03e4ebe2014-05-08 14:42:06 +010032
Elliott Hughes3a4c4542017-07-19 17:20:24 -070033#include <string>
Ryan Prichardc485cdb2019-04-30 14:47:34 -070034#include <thread>
Elliott Hughese6bb5a22015-01-23 17:48:15 -080035#include <vector>
36
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -080037#include <android-base/file.h>
Elliott Hughes141b9172021-04-09 17:13:09 -070038#include <android-base/silent_death_test.h>
Elliott Hughes8b86c0b2023-04-18 17:11:06 -070039#include <android-base/strings.h>
Elliott Hughes439ebbd2020-12-04 18:51:42 -080040#include <android-base/test_utils.h>
Elliott Hughes05b675e2019-04-17 13:01:06 -070041#include <android-base/unique_fd.h>
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -080042
Josh Gao2f06e102017-01-10 13:00:37 -080043#include "utils.h"
Elliott Hughes91875dc2012-09-24 17:55:15 -070044
Elliott Hughes05b675e2019-04-17 13:01:06 -070045// This #include is actually a test too. We have to duplicate the
46// definitions of the RENAME_ constants because <linux/fs.h> also contains
47// pollution such as BLOCK_SIZE which conflicts with lots of user code.
48// Important to check that we have matching definitions.
49// There's no _MAX to test that we have all the constants, sadly.
50#include <linux/fs.h>
51
Christopher Ferris13f26a72016-01-13 13:47:58 -080052#if defined(NOFORTIFY)
53#define STDIO_TEST stdio_nofortify
Elliott Hughesfb3873d2016-08-10 11:07:54 -070054#define STDIO_DEATHTEST stdio_nofortify_DeathTest
Christopher Ferris13f26a72016-01-13 13:47:58 -080055#else
56#define STDIO_TEST stdio
Elliott Hughesfb3873d2016-08-10 11:07:54 -070057#define STDIO_DEATHTEST stdio_DeathTest
Christopher Ferris13f26a72016-01-13 13:47:58 -080058#endif
59
Elliott Hughes3a4c4542017-07-19 17:20:24 -070060using namespace std::string_literals;
61
Elliott Hughes141b9172021-04-09 17:13:09 -070062using stdio_DeathTest = SilentDeathTest;
63using stdio_nofortify_DeathTest = SilentDeathTest;
Elliott Hughesfb3873d2016-08-10 11:07:54 -070064
Elliott Hughes33a8cb12017-07-25 18:06:46 -070065static void SetFileTo(const char* path, const char* content) {
66 FILE* fp;
67 ASSERT_NE(nullptr, fp = fopen(path, "w"));
68 ASSERT_NE(EOF, fputs(content, fp));
69 ASSERT_EQ(0, fclose(fp));
70}
71
72static void AssertFileIs(const char* path, const char* expected) {
73 FILE* fp;
74 ASSERT_NE(nullptr, fp = fopen(path, "r"));
75 char* line = nullptr;
76 size_t length;
77 ASSERT_NE(EOF, getline(&line, &length, fp));
78 ASSERT_EQ(0, fclose(fp));
79 ASSERT_STREQ(expected, line);
80 free(line);
81}
82
Elliott Hughes70715da2016-08-01 16:35:17 -070083static void AssertFileIs(FILE* fp, const char* expected, bool is_fmemopen = false) {
84 rewind(fp);
85
86 char line[1024];
Josh Gao2f06e102017-01-10 13:00:37 -080087 memset(line, 0xff, sizeof(line));
Elliott Hughes70715da2016-08-01 16:35:17 -070088 ASSERT_EQ(line, fgets(line, sizeof(line), fp));
89 ASSERT_STREQ(expected, line);
90
91 if (is_fmemopen) {
92 // fmemopen appends a trailing NUL byte, which probably shouldn't show up as an
93 // extra empty line, but does on every C library I tested...
94 ASSERT_EQ(line, fgets(line, sizeof(line), fp));
95 ASSERT_STREQ("", line);
96 }
97
98 // Make sure there isn't anything else in the file.
99 ASSERT_EQ(nullptr, fgets(line, sizeof(line), fp)) << "junk at end of file: " << line;
100}
101
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700102#define EXPECT_SNPRINTF_N(expected, n, fmt, ...) \
103 { \
104 char buf[BUFSIZ]; \
105 int w = snprintf(buf, sizeof(buf), fmt __VA_OPT__(, ) __VA_ARGS__); \
106 EXPECT_EQ(n, w); \
107 EXPECT_STREQ(expected, buf); \
108 }
109
110#define EXPECT_SNPRINTF(expected, fmt, ...) \
111 EXPECT_SNPRINTF_N(expected, static_cast<int>(strlen(expected)), fmt __VA_OPT__(, ) __VA_ARGS__)
112
113#define EXPECT_SWPRINTF_N(expected, n, fmt, ...) \
114 { \
115 wchar_t buf[BUFSIZ]; \
116 int w = swprintf(buf, sizeof(buf), fmt __VA_OPT__(, ) __VA_ARGS__); \
117 EXPECT_EQ(n, w); \
Elliott Hughes531199c2023-05-09 16:11:49 -0700118 EXPECT_EQ(std::wstring(expected), std::wstring(buf, w)); \
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700119 }
120#define EXPECT_SWPRINTF(expected, fmt, ...) \
121 EXPECT_SWPRINTF_N(expected, static_cast<int>(wcslen(expected)), fmt __VA_OPT__(, ) __VA_ARGS__)
122
Christopher Ferris13f26a72016-01-13 13:47:58 -0800123TEST(STDIO_TEST, flockfile_18208568_stderr) {
Elliott Hughes6a03abc2014-11-03 12:32:17 -0800124 // Check that we have a _recursive_ mutex for flockfile.
125 flockfile(stderr);
126 feof(stderr); // We don't care about the result, but this needs to take the lock.
127 funlockfile(stderr);
128}
129
Christopher Ferris13f26a72016-01-13 13:47:58 -0800130TEST(STDIO_TEST, flockfile_18208568_regular) {
Elliott Hughes6a03abc2014-11-03 12:32:17 -0800131 // We never had a bug for streams other than stdin/stdout/stderr, but test anyway.
132 FILE* fp = fopen("/dev/null", "w");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700133 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6a03abc2014-11-03 12:32:17 -0800134 flockfile(fp);
135 feof(fp);
136 funlockfile(fp);
137 fclose(fp);
138}
139
Christopher Ferris13f26a72016-01-13 13:47:58 -0800140TEST(STDIO_TEST, tmpfile_fileno_fprintf_rewind_fgets) {
Elliott Hughes91875dc2012-09-24 17:55:15 -0700141 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700142 ASSERT_TRUE(fp != nullptr);
Elliott Hughes91875dc2012-09-24 17:55:15 -0700143
144 int fd = fileno(fp);
145 ASSERT_NE(fd, -1);
146
147 struct stat sb;
148 int rc = fstat(fd, &sb);
149 ASSERT_NE(rc, -1);
150 ASSERT_EQ(sb.st_mode & 0777, 0600U);
151
152 rc = fprintf(fp, "hello\n");
153 ASSERT_EQ(rc, 6);
154
Elliott Hughes70715da2016-08-01 16:35:17 -0700155 AssertFileIs(fp, "hello\n");
Elliott Hughes91875dc2012-09-24 17:55:15 -0700156 fclose(fp);
157}
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300158
Elliott Hughesf226ee52016-02-03 11:24:28 -0800159TEST(STDIO_TEST, tmpfile64) {
160 FILE* fp = tmpfile64();
161 ASSERT_TRUE(fp != nullptr);
162 fclose(fp);
163}
164
Elliott Hughes8b86c0b2023-04-18 17:11:06 -0700165TEST(STDIO_TEST, tmpfile_TMPDIR) {
166 TemporaryDir td;
167 setenv("TMPDIR", td.path, 1);
168
169 FILE* fp = tmpfile();
170 ASSERT_TRUE(fp != nullptr);
171
172 std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fileno(fp));
173 char path[PATH_MAX];
174 ASSERT_GT(readlink(fd_path.c_str(), path, sizeof(path)), 0);
175 // $TMPDIR influenced where our temporary file ended up?
176 ASSERT_TRUE(android::base::StartsWith(path, td.path)) << path;
177 // And we used O_TMPFILE, right?
178 ASSERT_TRUE(android::base::EndsWith(path, " (deleted)")) << path;
179}
180
Christopher Ferris13f26a72016-01-13 13:47:58 -0800181TEST(STDIO_TEST, dprintf) {
Calin Juravle6afb2a92014-05-22 11:47:47 +0100182 TemporaryFile tf;
183
184 int rc = dprintf(tf.fd, "hello\n");
185 ASSERT_EQ(rc, 6);
186
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800187 lseek(tf.fd, 0, SEEK_SET);
Christopher Ferris9e01ea62014-05-29 12:49:35 -0700188 FILE* tfile = fdopen(tf.fd, "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700189 ASSERT_TRUE(tfile != nullptr);
Calin Juravle6afb2a92014-05-22 11:47:47 +0100190
Elliott Hughes70715da2016-08-01 16:35:17 -0700191 AssertFileIs(tfile, "hello\n");
Christopher Ferris9e01ea62014-05-29 12:49:35 -0700192 fclose(tfile);
Calin Juravle6afb2a92014-05-22 11:47:47 +0100193}
194
Christopher Ferris13f26a72016-01-13 13:47:58 -0800195TEST(STDIO_TEST, getdelim) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300196 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700197 ASSERT_TRUE(fp != nullptr);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300198
199 const char* line_written = "This is a test";
200 int rc = fprintf(fp, "%s", line_written);
201 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
202
203 rewind(fp);
204
Yi Kong32bc0fc2018-08-02 17:31:13 -0700205 char* word_read = nullptr;
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300206 size_t allocated_length = 0;
207
208 const char* expected[] = { "This ", " ", "is ", "a ", "test" };
209 for (size_t i = 0; i < 5; ++i) {
210 ASSERT_FALSE(feof(fp));
211 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i])));
212 ASSERT_GE(allocated_length, strlen(expected[i]));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800213 ASSERT_STREQ(expected[i], word_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300214 }
215 // The last read should have set the end-of-file indicator for the stream.
216 ASSERT_TRUE(feof(fp));
217 clearerr(fp);
218
219 // getdelim returns -1 but doesn't set errno if we're already at EOF.
220 // It should set the end-of-file indicator for the stream, though.
221 errno = 0;
222 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800223 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300224 ASSERT_TRUE(feof(fp));
225
226 free(word_read);
227 fclose(fp);
228}
229
Christopher Ferris13f26a72016-01-13 13:47:58 -0800230TEST(STDIO_TEST, getdelim_invalid) {
zijunzhao00a3dba2023-03-01 00:07:40 +0000231#pragma clang diagnostic push
232#pragma clang diagnostic ignored "-Wnonnull"
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300233 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700234 ASSERT_TRUE(fp != nullptr);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300235
Yi Kong32bc0fc2018-08-02 17:31:13 -0700236 char* buffer = nullptr;
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300237 size_t buffer_length = 0;
238
239 // The first argument can't be NULL.
240 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700241 ASSERT_EQ(getdelim(nullptr, &buffer_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800242 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300243
244 // The second argument can't be NULL.
245 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700246 ASSERT_EQ(getdelim(&buffer, nullptr, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800247 ASSERT_EQ(EINVAL, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700248 fclose(fp);
zijunzhao00a3dba2023-03-01 00:07:40 +0000249#pragma clang diagnostic pop
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300250}
251
Christopher Ferris13f26a72016-01-13 13:47:58 -0800252TEST(STDIO_TEST, getdelim_directory) {
Elliott Hughes694fd2d2015-04-05 10:51:56 -0700253 FILE* fp = fopen("/proc", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700254 ASSERT_TRUE(fp != nullptr);
Elliott Hughes694fd2d2015-04-05 10:51:56 -0700255 char* word_read;
256 size_t allocated_length;
257 ASSERT_EQ(-1, getdelim(&word_read, &allocated_length, ' ', fp));
258 fclose(fp);
259}
260
Christopher Ferris13f26a72016-01-13 13:47:58 -0800261TEST(STDIO_TEST, getline) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300262 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700263 ASSERT_TRUE(fp != nullptr);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300264
265 const char* line_written = "This is a test for getline\n";
266 const size_t line_count = 5;
267
268 for (size_t i = 0; i < line_count; ++i) {
269 int rc = fprintf(fp, "%s", line_written);
270 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
271 }
272
273 rewind(fp);
274
Yi Kong32bc0fc2018-08-02 17:31:13 -0700275 char* line_read = nullptr;
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300276 size_t allocated_length = 0;
277
278 size_t read_line_count = 0;
279 ssize_t read_char_count;
280 while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) {
281 ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written)));
282 ASSERT_GE(allocated_length, strlen(line_written));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800283 ASSERT_STREQ(line_written, line_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300284 ++read_line_count;
285 }
286 ASSERT_EQ(read_line_count, line_count);
287
288 // The last read should have set the end-of-file indicator for the stream.
289 ASSERT_TRUE(feof(fp));
290 clearerr(fp);
291
292 // getline returns -1 but doesn't set errno if we're already at EOF.
293 // It should set the end-of-file indicator for the stream, though.
294 errno = 0;
295 ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800296 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300297 ASSERT_TRUE(feof(fp));
298
299 free(line_read);
300 fclose(fp);
301}
302
Christopher Ferris13f26a72016-01-13 13:47:58 -0800303TEST(STDIO_TEST, getline_invalid) {
zijunzhao00a3dba2023-03-01 00:07:40 +0000304#pragma clang diagnostic push
305#pragma clang diagnostic ignored "-Wnonnull"
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300306 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700307 ASSERT_TRUE(fp != nullptr);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300308
Yi Kong32bc0fc2018-08-02 17:31:13 -0700309 char* buffer = nullptr;
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300310 size_t buffer_length = 0;
311
312 // The first argument can't be NULL.
313 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700314 ASSERT_EQ(getline(nullptr, &buffer_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800315 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300316
317 // The second argument can't be NULL.
318 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700319 ASSERT_EQ(getline(&buffer, nullptr, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800320 ASSERT_EQ(EINVAL, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700321 fclose(fp);
zijunzhao00a3dba2023-03-01 00:07:40 +0000322#pragma clang diagnostic pop
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300323}
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000324
Christopher Ferris13f26a72016-01-13 13:47:58 -0800325TEST(STDIO_TEST, printf_ssize_t) {
Elliott Hughese2556422013-02-28 10:51:14 -0800326 // http://b/8253769
Elliott Hughese2556422013-02-28 10:51:14 -0800327 ASSERT_EQ(sizeof(ssize_t), sizeof(long int));
Elliott Hughesb6e22482013-03-08 15:28:52 -0800328 ASSERT_EQ(sizeof(ssize_t), sizeof(size_t));
329 // For our 32-bit ABI, we had a ssize_t definition that confuses GCC into saying:
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000330 // error: format '%zd' expects argument of type 'signed size_t',
331 // but argument 4 has type 'ssize_t {aka long int}' [-Werror=format]
332 ssize_t v = 1;
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700333 EXPECT_SNPRINTF("1", "%zd", v);
334 EXPECT_SWPRINTF(L"1", L"%zd", v);
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000335}
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800336
Elliott Hughes05493712014-04-17 17:30:03 -0700337// https://code.google.com/p/android/issues/detail?id=64886
Christopher Ferris13f26a72016-01-13 13:47:58 -0800338TEST(STDIO_TEST, snprintf_a) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700339 EXPECT_SNPRINTF("<0x1.3831e147ae148p+13>", "<%a>", 9990.235);
340}
341
342// https://code.google.com/p/android/issues/detail?id=64886
343TEST(STDIO_TEST, swprintf_a) {
344 EXPECT_SWPRINTF(L"<0x1.3831e147ae148p+13>", L"<%a>", 9990.235);
Elliott Hughes05493712014-04-17 17:30:03 -0700345}
346
Elliott Hughescdb4a262020-06-05 16:56:53 -0700347// http://b/152588929
348TEST(STDIO_TEST, snprintf_La) {
349#if defined(__LP64__)
Elliott Hughescdb4a262020-06-05 16:56:53 -0700350 union {
351 uint64_t a[2];
352 long double v;
353 } u;
354
355 u.a[0] = UINT64_C(0x9b9b9b9b9b9b9b9b);
356 u.a[1] = UINT64_C(0xdfdfdfdfdfdfdfdf);
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700357 EXPECT_SNPRINTF("<-0x1.dfdfdfdfdfdf9b9b9b9b9b9b9b9bp+8160>", "<%La>", u.v);
Elliott Hughescdb4a262020-06-05 16:56:53 -0700358
359 u.a[0] = UINT64_C(0xffffffffffffffff);
360 u.a[1] = UINT64_C(0x7ffeffffffffffff);
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700361 EXPECT_SNPRINTF("<0x1.ffffffffffffffffffffffffffffp+16383>", "<%La>", u.v);
Elliott Hughescdb4a262020-06-05 16:56:53 -0700362
363 u.a[0] = UINT64_C(0x0000000000000000);
364 u.a[1] = UINT64_C(0x0000000000000000);
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700365 EXPECT_SNPRINTF("<0x0p+0>", "<%La>", u.v);
366#else
367 GTEST_SKIP() << "no ld128";
368#endif
369}
370
371// http://b/152588929
372TEST(STDIO_TEST, swprintf_La) {
373#if defined(__LP64__)
374 union {
375 uint64_t a[2];
376 long double v;
377 } u;
378
379 u.a[0] = UINT64_C(0x9b9b9b9b9b9b9b9b);
380 u.a[1] = UINT64_C(0xdfdfdfdfdfdfdfdf);
381 EXPECT_SWPRINTF(L"<-0x1.dfdfdfdfdfdf9b9b9b9b9b9b9b9bp+8160>", L"<%La>", u.v);
382
383 u.a[0] = UINT64_C(0xffffffffffffffff);
384 u.a[1] = UINT64_C(0x7ffeffffffffffff);
385 EXPECT_SWPRINTF(L"<0x1.ffffffffffffffffffffffffffffp+16383>", L"<%La>", u.v);
386
387 u.a[0] = UINT64_C(0x0000000000000000);
388 u.a[1] = UINT64_C(0x0000000000000000);
389 EXPECT_SWPRINTF(L"<0x0p+0>", L"<%La>", u.v);
Elliott Hughescdb4a262020-06-05 16:56:53 -0700390#else
391 GTEST_SKIP() << "no ld128";
392#endif
393}
394
Christopher Ferris13f26a72016-01-13 13:47:58 -0800395TEST(STDIO_TEST, snprintf_lc) {
Elliott Hughes05493712014-04-17 17:30:03 -0700396 wint_t wc = L'a';
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700397 EXPECT_SNPRINTF("<a>", "<%lc>", wc);
Elliott Hughes05493712014-04-17 17:30:03 -0700398}
399
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700400TEST(STDIO_TEST, swprintf_lc) {
401 wint_t wc = L'a';
402 EXPECT_SWPRINTF(L"<a>", L"<%lc>", wc);
403}
404
405TEST(STDIO_TEST, snprintf_C) { // Synonym for %lc.
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700406 wchar_t wc = L'a';
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700407 EXPECT_SNPRINTF("<a>", "<%C>", wc);
408}
409
410TEST(STDIO_TEST, swprintf_C) { // Synonym for %lc.
411 wchar_t wc = L'a';
412 EXPECT_SWPRINTF(L"<a>", L"<%C>", wc);
413}
414
415TEST(STDIO_TEST, snprintf_ls_null) {
416 EXPECT_SNPRINTF("<(null)>", "<%ls>", static_cast<wchar_t*>(nullptr));
417}
418
419TEST(STDIO_TEST, swprintf_ls_null) {
420 EXPECT_SWPRINTF(L"<(null)>", L"<%ls>", static_cast<wchar_t*>(nullptr));
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700421}
422
Christopher Ferris13f26a72016-01-13 13:47:58 -0800423TEST(STDIO_TEST, snprintf_ls) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700424 static const wchar_t chars[] = L"Hello\u0666 World";
425 EXPECT_SNPRINTF("<Hello\xd9\xa6 World>", "<%ls>", chars);
426}
Elliott Hughes05493712014-04-17 17:30:03 -0700427
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700428TEST(STDIO_TEST, swprintf_ls) {
429 static const wchar_t chars[] = L"Hello\u0666 World";
430 EXPECT_SWPRINTF(L"<Hello\u0666 World>", L"<%ls>", chars);
431}
432
433TEST(STDIO_TEST, snprintf_S_nullptr) { // Synonym for %ls.
434 EXPECT_SNPRINTF("<(null)>", "<%S>", static_cast<wchar_t*>(nullptr));
435}
436
437TEST(STDIO_TEST, swprintf_S_nullptr) { // Synonym for %ls.
438 EXPECT_SWPRINTF(L"<(null)>", L"<%S>", static_cast<wchar_t*>(nullptr));
Elliott Hughes05493712014-04-17 17:30:03 -0700439}
440
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700441TEST(STDIO_TEST, snprintf_S) { // Synonym for %ls.
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700442 static const wchar_t chars[] = L"Hello\u0666 World";
443 EXPECT_SNPRINTF("<Hello\xd9\xa6 World>", "<%S>", chars);
444}
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700445
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700446TEST(STDIO_TEST, swprintf_S) { // Synonym for %ls.
447 static const wchar_t chars[] = L"Hello\u0666 World";
448 EXPECT_SWPRINTF(L"<Hello\u0666 World>", L"<%S>", chars);
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700449}
450
Elliott Hughese657eb42021-02-18 17:11:56 -0800451TEST_F(STDIO_DEATHTEST, snprintf_n) {
Elliott Hughes063525c2014-05-13 11:19:57 -0700452#if defined(__BIONIC__)
Elliott Hughesb813a6a2022-08-01 22:18:40 +0000453#pragma clang diagnostic push
454#pragma clang diagnostic ignored "-Wformat"
Elliott Hughes41398d02018-03-07 13:32:58 -0800455 // http://b/14492135 and http://b/31832608.
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700456 char buf[32];
Elliott Hughese2341d02014-05-02 18:16:32 -0700457 int i = 1234;
Elliott Hughes41398d02018-03-07 13:32:58 -0800458 EXPECT_DEATH(snprintf(buf, sizeof(buf), "a %n b", &i), "%n not allowed on Android");
Elliott Hughesb813a6a2022-08-01 22:18:40 +0000459#pragma clang diagnostic pop
Elliott Hughese2341d02014-05-02 18:16:32 -0700460#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800461 GTEST_SKIP() << "glibc does allow %n";
Elliott Hughese2341d02014-05-02 18:16:32 -0700462#endif
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700463}
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700464
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700465TEST_F(STDIO_DEATHTEST, swprintf_n) {
466#if defined(__BIONIC__)
467#pragma clang diagnostic push
468#pragma clang diagnostic ignored "-Wformat"
469 // http://b/14492135 and http://b/31832608.
470 wchar_t buf[32];
471 int i = 1234;
472 EXPECT_DEATH(swprintf(buf, sizeof(buf), L"a %n b", &i), "%n not allowed on Android");
473#pragma clang diagnostic pop
474#else
475 GTEST_SKIP() << "glibc does allow %n";
476#endif
477}
478
Elliott Hughes7cebf832020-08-12 14:25:41 -0700479TEST(STDIO_TEST, snprintf_measure) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700480 char buf[1] = {'x'};
Elliott Hughes7cebf832020-08-12 14:25:41 -0700481 ASSERT_EQ(11, snprintf(buf, 0, "Hello %s", "world"));
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700482 ASSERT_EQ('x', buf[0]);
483}
484
485// Unlike snprintf(), you *can't* use swprintf() to measure.
486TEST(STDIO_TEST, swprintf_measure) {
487 wchar_t buf[1] = {L'x'};
488 ASSERT_EQ(-1, swprintf(buf, 0, L"Hello %S", L"world"));
489 ASSERT_EQ(L'x', buf[0]);
Elliott Hughes7cebf832020-08-12 14:25:41 -0700490}
491
Christopher Ferris13f26a72016-01-13 13:47:58 -0800492TEST(STDIO_TEST, snprintf_smoke) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700493 EXPECT_SNPRINTF("a", "a");
494 EXPECT_SNPRINTF("%", "%%");
495 EXPECT_SNPRINTF("01234", "01234");
496 EXPECT_SNPRINTF("a01234b", "a%sb", "01234");
Elliott Hughes1d13c642013-09-23 16:02:39 -0700497
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700498 EXPECT_SNPRINTF("a(null)b", "a%sb", static_cast<char*>(nullptr));
499 EXPECT_SNPRINTF("aabbcc", "aa%scc", "bb");
500 EXPECT_SNPRINTF("abc", "a%cc", 'b');
501 EXPECT_SNPRINTF("a1234b", "a%db", 1234);
502 EXPECT_SNPRINTF("a-8123b", "a%db", -8123);
503 EXPECT_SNPRINTF("a16b", "a%hdb", static_cast<short>(0x7fff0010));
504 EXPECT_SNPRINTF("a16b", "a%hhdb", static_cast<char>(0x7fffff10));
505 EXPECT_SNPRINTF("a68719476736b", "a%lldb", 0x1000000000LL);
506 EXPECT_SNPRINTF("a70000b", "a%ldb", 70000L);
507 EXPECT_SNPRINTF("a0xb0001234b", "a%pb", reinterpret_cast<void*>(0xb0001234));
508 EXPECT_SNPRINTF("a12abz", "a%xz", 0x12ab);
509 EXPECT_SNPRINTF("a12ABz", "a%Xz", 0x12ab);
510 EXPECT_SNPRINTF("a00123456z", "a%08xz", 0x123456);
511 EXPECT_SNPRINTF("a 1234z", "a%5dz", 1234);
512 EXPECT_SNPRINTF("a01234z", "a%05dz", 1234);
513 EXPECT_SNPRINTF("a 1234z", "a%8dz", 1234);
514 EXPECT_SNPRINTF("a1234 z", "a%-8dz", 1234);
515 EXPECT_SNPRINTF("Aabcdef Z", "A%-11sZ", "abcdef");
516 EXPECT_SNPRINTF("Ahello:1234Z", "A%s:%dZ", "hello", 1234);
517 EXPECT_SNPRINTF("a005:5:05z", "a%03d:%d:%02dz", 5, 5, 5);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700518
Christopher Ferris13613132013-10-28 15:24:04 -0700519#if defined(__BIONIC__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700520 EXPECT_SNPRINTF("a5,0x0z", "a%d,%pz", 5, static_cast<void*>(nullptr));
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800521#else // __BIONIC__
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700522 EXPECT_SNPRINTF("a5,(nil)z", "a%d,%pz", 5, static_cast<void*>(nullptr));
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800523#endif // __BIONIC__
Elliott Hughes1d13c642013-09-23 16:02:39 -0700524
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700525 EXPECT_SNPRINTF("a68719476736,6,7,8z", "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700526
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700527 EXPECT_SNPRINTF("a_1.230000_b", "a_%f_b", 1.23f);
528 EXPECT_SNPRINTF("a_3.14_b", "a_%g_b", 3.14);
529 EXPECT_SNPRINTF("print_me_twice print_me_twice", "%1$s %1$s", "print_me_twice");
530}
Elliott Hughes1d13c642013-09-23 16:02:39 -0700531
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700532TEST(STDIO_TEST, swprintf_smoke) {
533 EXPECT_SWPRINTF(L"a", L"a");
534 EXPECT_SWPRINTF(L"%", L"%%");
535 EXPECT_SWPRINTF(L"01234", L"01234");
536 EXPECT_SWPRINTF(L"a01234b", L"a%sb", "01234");
Alexander Ivchenkoedd7c2e2014-04-01 17:01:39 +0400537
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700538 EXPECT_SWPRINTF(L"a(null)b", L"a%sb", static_cast<char*>(nullptr));
539 EXPECT_SWPRINTF(L"aabbcc", L"aa%scc", "bb");
540 EXPECT_SWPRINTF(L"abc", L"a%cc", 'b');
541 EXPECT_SWPRINTF(L"a1234b", L"a%db", 1234);
542 EXPECT_SWPRINTF(L"a-8123b", L"a%db", -8123);
543 EXPECT_SWPRINTF(L"a16b", L"a%hdb", static_cast<short>(0x7fff0010));
544 EXPECT_SWPRINTF(L"a16b", L"a%hhdb", static_cast<char>(0x7fffff10));
545 EXPECT_SWPRINTF(L"a68719476736b", L"a%lldb", 0x1000000000LL);
546 EXPECT_SWPRINTF(L"a70000b", L"a%ldb", 70000L);
547 EXPECT_SWPRINTF(L"a0xb0001234b", L"a%pb", reinterpret_cast<void*>(0xb0001234));
548 EXPECT_SWPRINTF(L"a12abz", L"a%xz", 0x12ab);
549 EXPECT_SWPRINTF(L"a12ABz", L"a%Xz", 0x12ab);
550 EXPECT_SWPRINTF(L"a00123456z", L"a%08xz", 0x123456);
551 EXPECT_SWPRINTF(L"a 1234z", L"a%5dz", 1234);
552 EXPECT_SWPRINTF(L"a01234z", L"a%05dz", 1234);
553 EXPECT_SWPRINTF(L"a 1234z", L"a%8dz", 1234);
554 EXPECT_SWPRINTF(L"a1234 z", L"a%-8dz", 1234);
555 EXPECT_SWPRINTF(L"Aabcdef Z", L"A%-11sZ", "abcdef");
556 EXPECT_SWPRINTF(L"Ahello:1234Z", L"A%s:%dZ", "hello", 1234);
557 EXPECT_SWPRINTF(L"a005:5:05z", L"a%03d:%d:%02dz", 5, 5, 5);
558
559#if defined(__BIONIC__)
560 EXPECT_SWPRINTF(L"a5,0x0z", L"a%d,%pz", 5, static_cast<void*>(nullptr));
561#else // __BIONIC__
562 EXPECT_SWPRINTF(L"a5,(nil)z", L"a%d,%pz", 5, static_cast<void*>(nullptr));
563#endif // __BIONIC__
564
565 EXPECT_SWPRINTF(L"a68719476736,6,7,8z", L"a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
566
567 EXPECT_SWPRINTF(L"a_1.230000_b", L"a_%f_b", 1.23f);
568 EXPECT_SWPRINTF(L"a_3.14_b", L"a_%g_b", 3.14);
569 EXPECT_SWPRINTF(L"print_me_twice print_me_twice", L"%1$s %1$s", "print_me_twice");
Elliott Hughes1d13c642013-09-23 16:02:39 -0700570}
571
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800572template <typename T>
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700573static void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...),
574 int sscanf_fn(const T*, const T*, ...),
575 const T* fmt_string, const T* fmt, const T* fmt_plus,
576 const T* minus_inf, const T* inf_, const T* plus_inf,
577 const T* minus_nan, const T* nan_, const T* plus_nan) {
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800578 T buf[BUFSIZ];
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700579 float f;
Elliott Hughes7823f322014-04-14 12:11:28 -0700580
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700581 // NaN.
582
Elliott Hughese0a9a382022-10-25 22:56:43 +0000583 snprintf_fn(buf, sizeof(buf), fmt, nan(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800584 EXPECT_STREQ(nan_, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700585 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
586 EXPECT_TRUE(isnan(f));
587
Elliott Hughese0a9a382022-10-25 22:56:43 +0000588 snprintf_fn(buf, sizeof(buf), fmt, -nan(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800589 EXPECT_STREQ(minus_nan, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700590 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
591 EXPECT_TRUE(isnan(f));
592
Elliott Hughese0a9a382022-10-25 22:56:43 +0000593 snprintf_fn(buf, sizeof(buf), fmt_plus, nan(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800594 EXPECT_STREQ(plus_nan, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700595 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
596 EXPECT_TRUE(isnan(f));
597
Elliott Hughese0a9a382022-10-25 22:56:43 +0000598 snprintf_fn(buf, sizeof(buf), fmt_plus, -nan(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800599 EXPECT_STREQ(minus_nan, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700600 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
601 EXPECT_TRUE(isnan(f));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800602
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700603 // Inf.
604
605 snprintf_fn(buf, sizeof(buf), fmt, HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800606 EXPECT_STREQ(inf_, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700607 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
608 EXPECT_EQ(HUGE_VALF, f);
609
610 snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800611 EXPECT_STREQ(minus_inf, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700612 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
613 EXPECT_EQ(-HUGE_VALF, f);
614
615 snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800616 EXPECT_STREQ(plus_inf, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700617 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
618 EXPECT_EQ(HUGE_VALF, f);
619
620 snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800621 EXPECT_STREQ(minus_inf, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700622 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
623 EXPECT_EQ(-HUGE_VALF, f);
624
625 // Check case-insensitivity.
626 snprintf_fn(buf, sizeof(buf), fmt_string, "[InFiNiTy]");
627 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f)) << buf;
628 EXPECT_EQ(HUGE_VALF, f);
629 snprintf_fn(buf, sizeof(buf), fmt_string, "[NaN]");
630 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f)) << buf;
631 EXPECT_TRUE(isnan(f));
Elliott Hughes7823f322014-04-14 12:11:28 -0700632}
633
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700634TEST(STDIO_TEST, snprintf_sscanf_inf_nan) {
635 CheckInfNan(snprintf, sscanf, "%s",
636 "[%a]", "[%+a]",
637 "[-inf]", "[inf]", "[+inf]",
638 "[-nan]", "[nan]", "[+nan]");
639 CheckInfNan(snprintf, sscanf, "%s",
640 "[%A]", "[%+A]",
641 "[-INF]", "[INF]", "[+INF]",
642 "[-NAN]", "[NAN]", "[+NAN]");
643 CheckInfNan(snprintf, sscanf, "%s",
644 "[%e]", "[%+e]",
645 "[-inf]", "[inf]", "[+inf]",
646 "[-nan]", "[nan]", "[+nan]");
647 CheckInfNan(snprintf, sscanf, "%s",
648 "[%E]", "[%+E]",
649 "[-INF]", "[INF]", "[+INF]",
650 "[-NAN]", "[NAN]", "[+NAN]");
651 CheckInfNan(snprintf, sscanf, "%s",
652 "[%f]", "[%+f]",
653 "[-inf]", "[inf]", "[+inf]",
654 "[-nan]", "[nan]", "[+nan]");
655 CheckInfNan(snprintf, sscanf, "%s",
656 "[%F]", "[%+F]",
657 "[-INF]", "[INF]", "[+INF]",
658 "[-NAN]", "[NAN]", "[+NAN]");
659 CheckInfNan(snprintf, sscanf, "%s",
660 "[%g]", "[%+g]",
661 "[-inf]", "[inf]", "[+inf]",
662 "[-nan]", "[nan]", "[+nan]");
663 CheckInfNan(snprintf, sscanf, "%s",
664 "[%G]", "[%+G]",
665 "[-INF]", "[INF]", "[+INF]",
666 "[-NAN]", "[NAN]", "[+NAN]");
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800667}
Elliott Hughes7823f322014-04-14 12:11:28 -0700668
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700669TEST(STDIO_TEST, swprintf_swscanf_inf_nan) {
670 CheckInfNan(swprintf, swscanf, L"%s",
671 L"[%a]", L"[%+a]",
672 L"[-inf]", L"[inf]", L"[+inf]",
673 L"[-nan]", L"[nan]", L"[+nan]");
674 CheckInfNan(swprintf, swscanf, L"%s",
675 L"[%A]", L"[%+A]",
676 L"[-INF]", L"[INF]", L"[+INF]",
677 L"[-NAN]", L"[NAN]", L"[+NAN]");
678 CheckInfNan(swprintf, swscanf, L"%s",
679 L"[%e]", L"[%+e]",
680 L"[-inf]", L"[inf]", L"[+inf]",
681 L"[-nan]", L"[nan]", L"[+nan]");
682 CheckInfNan(swprintf, swscanf, L"%s",
683 L"[%E]", L"[%+E]",
684 L"[-INF]", L"[INF]", L"[+INF]",
685 L"[-NAN]", L"[NAN]", L"[+NAN]");
686 CheckInfNan(swprintf, swscanf, L"%s",
687 L"[%f]", L"[%+f]",
688 L"[-inf]", L"[inf]", L"[+inf]",
689 L"[-nan]", L"[nan]", L"[+nan]");
690 CheckInfNan(swprintf, swscanf, L"%s",
691 L"[%F]", L"[%+F]",
692 L"[-INF]", L"[INF]", L"[+INF]",
693 L"[-NAN]", L"[NAN]", L"[+NAN]");
694 CheckInfNan(swprintf, swscanf, L"%s",
695 L"[%g]", L"[%+g]",
696 L"[-inf]", L"[inf]", L"[+inf]",
697 L"[-nan]", L"[nan]", L"[+nan]");
698 CheckInfNan(swprintf, swscanf, L"%s",
699 L"[%G]", L"[%+G]",
700 L"[-INF]", L"[INF]", L"[+INF]",
701 L"[-NAN]", L"[NAN]", L"[+NAN]");
Elliott Hughes7823f322014-04-14 12:11:28 -0700702}
703
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700704TEST(STDIO_TEST, snprintf_jd_INTMAX_MAX) {
705 EXPECT_SNPRINTF("9223372036854775807", "%jd", INTMAX_MAX);
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700706}
707
Elliott Hughes618303c2017-11-02 16:58:44 -0700708TEST(STDIO_TEST, swprintf_jd_INTMAX_MAX) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700709 EXPECT_SWPRINTF(L"9223372036854775807", L"%jd", INTMAX_MAX);
Elliott Hughes618303c2017-11-02 16:58:44 -0700710}
711
712TEST(STDIO_TEST, snprintf_jd_INTMAX_MIN) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700713 EXPECT_SNPRINTF("-9223372036854775808", "%jd", INTMAX_MIN);
714}
715
716TEST(STDIO_TEST, swprintf_jd_INTMAX_MIN) {
717 EXPECT_SWPRINTF(L"-9223372036854775808", L"%jd", INTMAX_MIN);
Elliott Hughes618303c2017-11-02 16:58:44 -0700718}
719
720TEST(STDIO_TEST, snprintf_ju_UINTMAX_MAX) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700721 EXPECT_SNPRINTF("18446744073709551615", "%ju", UINTMAX_MAX);
722}
723
724TEST(STDIO_TEST, swprintf_ju_UINTMAX_MAX) {
725 EXPECT_SWPRINTF(L"18446744073709551615", L"%ju", UINTMAX_MAX);
Elliott Hughes618303c2017-11-02 16:58:44 -0700726}
727
728TEST(STDIO_TEST, snprintf_1$ju_UINTMAX_MAX) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700729 EXPECT_SNPRINTF("18446744073709551615", "%1$ju", UINTMAX_MAX);
730}
731
732TEST(STDIO_TEST, swprintf_1$ju_UINTMAX_MAX) {
733 EXPECT_SWPRINTF(L"18446744073709551615", L"%1$ju", UINTMAX_MAX);
734}
735
736TEST(STDIO_TEST, snprintf_d_INT_MAX) {
737 EXPECT_SNPRINTF("2147483647", "%d", INT_MAX);
738}
739
740TEST(STDIO_TEST, swprintf_d_INT_MAX) {
741 EXPECT_SWPRINTF(L"2147483647", L"%d", INT_MAX);
742}
743
744TEST(STDIO_TEST, snprintf_d_INT_MIN) {
745 EXPECT_SNPRINTF("-2147483648", "%d", INT_MIN);
746}
747
748TEST(STDIO_TEST, swprintf_d_INT_MIN) {
749 EXPECT_SWPRINTF(L"-2147483648", L"%d", INT_MIN);
Elliott Hughes618303c2017-11-02 16:58:44 -0700750}
751
Christopher Ferris13f26a72016-01-13 13:47:58 -0800752TEST(STDIO_TEST, snprintf_ld_LONG_MAX) {
Josh Gaob36efa42016-09-15 13:55:41 -0700753#if defined(__LP64__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700754 EXPECT_SNPRINTF("9223372036854775807", "%ld", LONG_MAX);
Elliott Hughes925753a2013-10-18 13:17:18 -0700755#else
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700756 EXPECT_SNPRINTF("2147483647", "%ld", LONG_MAX);
757#endif
758}
759
760TEST(STDIO_TEST, swprintf_ld_LONG_MAX) {
761#if defined(__LP64__)
762 EXPECT_SWPRINTF(L"9223372036854775807", L"%ld", LONG_MAX);
763#else
764 EXPECT_SWPRINTF(L"2147483647", L"%ld", LONG_MAX);
Elliott Hughes925753a2013-10-18 13:17:18 -0700765#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700766}
767
Christopher Ferris13f26a72016-01-13 13:47:58 -0800768TEST(STDIO_TEST, snprintf_ld_LONG_MIN) {
Josh Gaob36efa42016-09-15 13:55:41 -0700769#if defined(__LP64__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700770 EXPECT_SNPRINTF("-9223372036854775808", "%ld", LONG_MIN);
Elliott Hughes925753a2013-10-18 13:17:18 -0700771#else
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700772 EXPECT_SNPRINTF("-2147483648", "%ld", LONG_MIN);
773#endif
774}
775
776TEST(STDIO_TEST, swprintf_ld_LONG_MIN) {
777#if defined(__LP64__)
778 EXPECT_SWPRINTF(L"-9223372036854775808", L"%ld", LONG_MIN);
779#else
780 EXPECT_SWPRINTF(L"-2147483648", L"%ld", LONG_MIN);
Elliott Hughes925753a2013-10-18 13:17:18 -0700781#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700782}
783
Christopher Ferris13f26a72016-01-13 13:47:58 -0800784TEST(STDIO_TEST, snprintf_lld_LLONG_MAX) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700785 EXPECT_SNPRINTF("9223372036854775807", "%lld", LLONG_MAX);
786}
787
788TEST(STDIO_TEST, swprintf_lld_LLONG_MAX) {
789 EXPECT_SWPRINTF(L"9223372036854775807", L"%lld", LLONG_MAX);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700790}
791
Christopher Ferris13f26a72016-01-13 13:47:58 -0800792TEST(STDIO_TEST, snprintf_lld_LLONG_MIN) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700793 EXPECT_SNPRINTF("-9223372036854775808", "%lld", LLONG_MIN);
794}
795
796TEST(STDIO_TEST, swprintf_lld_LLONG_MIN) {
797 EXPECT_SWPRINTF(L"-9223372036854775808", L"%lld", LLONG_MIN);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700798}
799
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700800TEST(STDIO_TEST, snprintf_o_UINT_MAX) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700801 EXPECT_SNPRINTF("37777777777", "%o", UINT_MAX);
802}
803
804TEST(STDIO_TEST, swprintf_o_UINT_MAX) {
805 EXPECT_SWPRINTF(L"37777777777", L"%o", UINT_MAX);
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700806}
807
808TEST(STDIO_TEST, snprintf_u_UINT_MAX) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700809 EXPECT_SNPRINTF("4294967295", "%u", UINT_MAX);
810}
811
812TEST(STDIO_TEST, swprintf_u_UINT_MAX) {
813 EXPECT_SWPRINTF(L"4294967295", L"%u", UINT_MAX);
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700814}
815
816TEST(STDIO_TEST, snprintf_x_UINT_MAX) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700817 EXPECT_SNPRINTF("ffffffff", "%x", UINT_MAX);
818}
819
820TEST(STDIO_TEST, swprintf_x_UINT_MAX) {
821 EXPECT_SWPRINTF(L"ffffffff", L"%x", UINT_MAX);
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700822}
823
824TEST(STDIO_TEST, snprintf_X_UINT_MAX) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700825 EXPECT_SNPRINTF("FFFFFFFF", "%X", UINT_MAX);
826}
827
828TEST(STDIO_TEST, swprintf_X_UINT_MAX) {
829 EXPECT_SWPRINTF(L"FFFFFFFF", L"%X", UINT_MAX);
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700830}
831
Christopher Ferris13f26a72016-01-13 13:47:58 -0800832TEST(STDIO_TEST, snprintf_e) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700833 EXPECT_SNPRINTF("1.500000e+00", "%e", 1.5);
834 EXPECT_SNPRINTF("1.500000e+00", "%Le", 1.5L);
835}
Elliott Hughes4bd97ce2014-04-10 17:48:14 -0700836
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700837TEST(STDIO_TEST, swprintf_e) {
838 EXPECT_SWPRINTF(L"1.500000e+00", L"%e", 1.5);
839 EXPECT_SWPRINTF(L"1.500000e+00", L"%Le", 1.5L);
Elliott Hughes4bd97ce2014-04-10 17:48:14 -0700840}
841
Christopher Ferris13f26a72016-01-13 13:47:58 -0800842TEST(STDIO_TEST, snprintf_negative_zero_5084292) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700843 EXPECT_SNPRINTF("-0.000000e+00", "%e", -0.0);
844 EXPECT_SNPRINTF("-0.000000E+00", "%E", -0.0);
845 EXPECT_SNPRINTF("-0.000000", "%f", -0.0);
846 EXPECT_SNPRINTF("-0.000000", "%F", -0.0);
847 EXPECT_SNPRINTF("-0", "%g", -0.0);
848 EXPECT_SNPRINTF("-0", "%G", -0.0);
849 EXPECT_SNPRINTF("-0x0p+0", "%a", -0.0);
850 EXPECT_SNPRINTF("-0X0P+0", "%A", -0.0);
851}
Elliott Hughese77f38f2014-05-14 12:39:12 -0700852
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700853TEST(STDIO_TEST, swprintf_negative_zero_5084292) {
854 EXPECT_SWPRINTF(L"-0.000000e+00", L"%e", -0.0);
855 EXPECT_SWPRINTF(L"-0.000000E+00", L"%E", -0.0);
856 EXPECT_SWPRINTF(L"-0.000000", L"%f", -0.0);
857 EXPECT_SWPRINTF(L"-0.000000", L"%F", -0.0);
858 EXPECT_SWPRINTF(L"-0", L"%g", -0.0);
859 EXPECT_SWPRINTF(L"-0", L"%G", -0.0);
860 EXPECT_SWPRINTF(L"-0x0p+0", L"%a", -0.0);
861 EXPECT_SWPRINTF(L"-0X0P+0", L"%A", -0.0);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700862}
863
Christopher Ferris13f26a72016-01-13 13:47:58 -0800864TEST(STDIO_TEST, snprintf_utf8_15439554) {
Yi Kong32bc0fc2018-08-02 17:31:13 -0700865 locale_t cloc = newlocale(LC_ALL, "C.UTF-8", nullptr);
Wally Yaua40fdbd2014-08-26 09:47:23 -0700866 locale_t old_locale = uselocale(cloc);
Dan Albert1aec7c12014-07-30 10:53:48 -0700867
Elliott Hughes69f05d22014-06-05 20:10:09 -0700868 // http://b/15439554
869 char buf[BUFSIZ];
870
871 // 1-byte character.
872 snprintf(buf, sizeof(buf), "%dx%d", 1, 2);
873 EXPECT_STREQ("1x2", buf);
874 // 2-byte character.
875 snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2);
876 EXPECT_STREQ("1¢2", buf);
877 // 3-byte character.
878 snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2);
879 EXPECT_STREQ("1€2", buf);
880 // 4-byte character.
881 snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2);
882 EXPECT_STREQ("1𤭢2", buf);
Dan Albert1aec7c12014-07-30 10:53:48 -0700883
Wally Yaua40fdbd2014-08-26 09:47:23 -0700884 uselocale(old_locale);
Dan Albert1aec7c12014-07-30 10:53:48 -0700885 freelocale(cloc);
Elliott Hughes69f05d22014-06-05 20:10:09 -0700886}
887
Elliott Hughes43f7c872016-02-05 11:18:41 -0800888static void* snprintf_small_stack_fn(void*) {
889 // Make life (realistically) hard for ourselves by allocating our own buffer for the result.
890 char buf[PATH_MAX];
891 snprintf(buf, sizeof(buf), "/proc/%d", getpid());
892 return nullptr;
893}
894
895TEST(STDIO_TEST, snprintf_small_stack) {
896 // Is it safe to call snprintf on a thread with a small stack?
897 // (The snprintf implementation puts some pretty large buffers on the stack.)
898 pthread_attr_t a;
899 ASSERT_EQ(0, pthread_attr_init(&a));
900 ASSERT_EQ(0, pthread_attr_setstacksize(&a, PTHREAD_STACK_MIN));
901
902 pthread_t t;
903 ASSERT_EQ(0, pthread_create(&t, &a, snprintf_small_stack_fn, nullptr));
904 ASSERT_EQ(0, pthread_join(t, nullptr));
905}
906
Elliott Hughes8200e552016-02-05 21:57:37 -0800907TEST(STDIO_TEST, snprintf_asterisk_overflow) {
908 char buf[128];
909 ASSERT_EQ(5, snprintf(buf, sizeof(buf), "%.*s%c", 4, "hello world", '!'));
910 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX/2, "hello world", '!'));
911 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX-1, "hello world", '!'));
912 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX, "hello world", '!'));
913 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", -1, "hello world", '!'));
914
915 // INT_MAX-1, INT_MAX, INT_MAX+1.
916 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483646s%c", "hello world", '!'));
917 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483647s%c", "hello world", '!'));
918 ASSERT_EQ(-1, snprintf(buf, sizeof(buf), "%.2147483648s%c", "hello world", '!'));
919 ASSERT_EQ(ENOMEM, errno);
920}
921
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700922TEST(STDIO_TEST, swprintf_asterisk_overflow) {
923 wchar_t buf[128];
924 ASSERT_EQ(5, swprintf(buf, sizeof(buf), L"%.*s%c", 4, "hello world", '!'));
925 ASSERT_EQ(12, swprintf(buf, sizeof(buf), L"%.*s%c", INT_MAX / 2, "hello world", '!'));
926 ASSERT_EQ(12, swprintf(buf, sizeof(buf), L"%.*s%c", INT_MAX - 1, "hello world", '!'));
927 ASSERT_EQ(12, swprintf(buf, sizeof(buf), L"%.*s%c", INT_MAX, "hello world", '!'));
928 ASSERT_EQ(12, swprintf(buf, sizeof(buf), L"%.*s%c", -1, "hello world", '!'));
929
930 // INT_MAX-1, INT_MAX, INT_MAX+1.
931 ASSERT_EQ(12, swprintf(buf, sizeof(buf), L"%.2147483646s%c", "hello world", '!'));
932 ASSERT_EQ(12, swprintf(buf, sizeof(buf), L"%.2147483647s%c", "hello world", '!'));
933 ASSERT_EQ(-1, swprintf(buf, sizeof(buf), L"%.2147483648s%c", "hello world", '!'));
934 ASSERT_EQ(ENOMEM, errno);
935}
936
Elliott Hughes5dc31302020-01-07 08:48:10 -0800937// Inspired by https://github.com/landley/toybox/issues/163.
938TEST(STDIO_TEST, printf_NULL) {
Elliott Hughes5dc31302020-01-07 08:48:10 -0800939 char* null = nullptr;
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700940 EXPECT_SNPRINTF("<(n>", "<%*.*s>", 2, 2, null);
941 EXPECT_SNPRINTF("<(null)>", "<%*.*s>", 2, 8, null);
942 EXPECT_SNPRINTF("< (n>", "<%*.*s>", 8, 2, null);
943 EXPECT_SNPRINTF("< (null)>", "<%*.*s>", 8, 8, null);
944}
945
946TEST(STDIO_TEST, wprintf_NULL) {
947 char* null = nullptr;
948 EXPECT_SWPRINTF(L"<(n>", L"<%*.*s>", 2, 2, null);
949 EXPECT_SWPRINTF(L"<(null)>", L"<%*.*s>", 2, 8, null);
950 EXPECT_SWPRINTF(L"< (n>", L"<%*.*s>", 8, 2, null);
951 EXPECT_SWPRINTF(L"< (null)>", L"<%*.*s>", 8, 8, null);
Elliott Hughes5dc31302020-01-07 08:48:10 -0800952}
953
Elliott Hughes70715da2016-08-01 16:35:17 -0700954TEST(STDIO_TEST, fprintf) {
955 TemporaryFile tf;
956
957 FILE* tfile = fdopen(tf.fd, "r+");
958 ASSERT_TRUE(tfile != nullptr);
959
960 ASSERT_EQ(7, fprintf(tfile, "%d %s", 123, "abc"));
961 AssertFileIs(tfile, "123 abc");
962 fclose(tfile);
963}
964
Christopher Ferris13f26a72016-01-13 13:47:58 -0800965TEST(STDIO_TEST, fprintf_failures_7229520) {
Elliott Hughes69f05d22014-06-05 20:10:09 -0700966 // http://b/7229520
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700967 FILE* fp;
Josh Gaof6e5b582018-06-01 15:30:54 -0700968 int fd_rdonly = open("/dev/null", O_RDONLY);
969 ASSERT_NE(-1, fd_rdonly);
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700970
971 // Unbuffered case where the fprintf(3) itself fails.
972 ASSERT_NE(nullptr, fp = tmpfile());
Yi Kong32bc0fc2018-08-02 17:31:13 -0700973 setbuf(fp, nullptr);
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700974 ASSERT_EQ(4, fprintf(fp, "epic"));
Josh Gaof6e5b582018-06-01 15:30:54 -0700975 ASSERT_NE(-1, dup2(fd_rdonly, fileno(fp)));
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700976 ASSERT_EQ(-1, fprintf(fp, "fail"));
Josh Gaof6e5b582018-06-01 15:30:54 -0700977 ASSERT_EQ(0, fclose(fp));
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700978
979 // Buffered case where we won't notice until the fclose(3).
980 // It's likely this is what was actually seen in http://b/7229520,
981 // and that expecting fprintf to fail is setting yourself up for
982 // disappointment. Remember to check fclose(3)'s return value, kids!
983 ASSERT_NE(nullptr, fp = tmpfile());
984 ASSERT_EQ(4, fprintf(fp, "epic"));
Josh Gaof6e5b582018-06-01 15:30:54 -0700985 ASSERT_NE(-1, dup2(fd_rdonly, fileno(fp)));
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700986 ASSERT_EQ(4, fprintf(fp, "fail"));
987 ASSERT_EQ(-1, fclose(fp));
988}
989
Elliott Hughes468efc82018-07-10 14:39:49 -0700990TEST(STDIO_TEST, popen_r) {
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800991 FILE* fp = popen("cat /proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700992 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800993
994 char buf[16];
995 char* s = fgets(buf, sizeof(buf), fp);
996 buf[13] = '\0';
997 ASSERT_STREQ("Linux version", s);
998
999 ASSERT_EQ(0, pclose(fp));
1000}
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001001
Elliott Hughes468efc82018-07-10 14:39:49 -07001002TEST(STDIO_TEST, popen_socketpair) {
1003 FILE* fp = popen("cat", "r+");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001004 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -07001005
1006 fputs("hello\nworld\n", fp);
1007 fflush(fp);
1008
1009 char buf[16];
1010 ASSERT_NE(nullptr, fgets(buf, sizeof(buf), fp));
1011 EXPECT_STREQ("hello\n", buf);
1012 ASSERT_NE(nullptr, fgets(buf, sizeof(buf), fp));
1013 EXPECT_STREQ("world\n", buf);
1014
1015 ASSERT_EQ(0, pclose(fp));
1016}
1017
1018TEST(STDIO_TEST, popen_socketpair_shutdown) {
1019 FILE* fp = popen("uniq -c", "r+");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001020 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -07001021
1022 fputs("a\na\na\na\nb\n", fp);
1023 fflush(fp);
1024 ASSERT_EQ(0, shutdown(fileno(fp), SHUT_WR));
1025
1026 char buf[16];
1027 ASSERT_NE(nullptr, fgets(buf, sizeof(buf), fp));
1028 EXPECT_STREQ(" 4 a\n", buf);
1029 ASSERT_NE(nullptr, fgets(buf, sizeof(buf), fp));
1030 EXPECT_STREQ(" 1 b\n", buf);
1031
1032 ASSERT_EQ(0, pclose(fp));
1033}
1034
1035TEST(STDIO_TEST, popen_return_value_0) {
1036 FILE* fp = popen("true", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001037 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -07001038 int status = pclose(fp);
1039 EXPECT_TRUE(WIFEXITED(status));
1040 EXPECT_EQ(0, WEXITSTATUS(status));
1041}
1042
1043TEST(STDIO_TEST, popen_return_value_1) {
1044 FILE* fp = popen("false", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001045 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -07001046 int status = pclose(fp);
1047 EXPECT_TRUE(WIFEXITED(status));
1048 EXPECT_EQ(1, WEXITSTATUS(status));
1049}
1050
1051TEST(STDIO_TEST, popen_return_value_signal) {
1052 FILE* fp = popen("kill -7 $$", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001053 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -07001054 int status = pclose(fp);
1055 EXPECT_TRUE(WIFSIGNALED(status));
1056 EXPECT_EQ(7, WTERMSIG(status));
1057}
1058
Christopher Ferris13f26a72016-01-13 13:47:58 -08001059TEST(STDIO_TEST, getc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001060 FILE* fp = fopen("/proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001061 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001062 ASSERT_EQ('L', getc(fp));
1063 ASSERT_EQ('i', getc(fp));
1064 ASSERT_EQ('n', getc(fp));
1065 ASSERT_EQ('u', getc(fp));
1066 ASSERT_EQ('x', getc(fp));
1067 fclose(fp);
1068}
1069
Christopher Ferris13f26a72016-01-13 13:47:58 -08001070TEST(STDIO_TEST, putc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001071 FILE* fp = fopen("/proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001072 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001073 ASSERT_EQ(EOF, putc('x', fp));
1074 fclose(fp);
1075}
Elliott Hughes603332f2014-03-12 17:10:41 -07001076
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001077TEST(STDIO_TEST, sscanf_swscanf) {
1078 struct stuff {
1079 char s1[123];
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001080 int i1, i2;
1081 char cs1[3];
1082 char s2[3];
1083 char c1;
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001084 double d1;
1085 float f1;
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001086 char s3[123];
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001087
1088 void Check() {
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001089 EXPECT_STREQ("hello", s1);
1090 EXPECT_EQ(123, i1);
1091 EXPECT_EQ(456, i2);
1092 EXPECT_EQ('a', cs1[0]);
1093 EXPECT_EQ('b', cs1[1]);
1094 EXPECT_EQ('x', cs1[2]); // No terminating NUL.
1095 EXPECT_STREQ("AB", s2); // Terminating NUL.
1096 EXPECT_EQ('!', c1);
1097 EXPECT_DOUBLE_EQ(1.23, d1);
1098 EXPECT_FLOAT_EQ(9.0f, f1);
1099 EXPECT_STREQ("world", s3);
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001100 }
1101 } s;
1102
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001103 memset(&s, 'x', sizeof(s));
1104 ASSERT_EQ(9, sscanf(" hello 123 456abAB! 1.23 0x1.2p3 world",
1105 "%s %i%i%2c%[A-Z]%c %lf %f %s",
1106 s.s1, &s.i1, &s.i2, s.cs1, s.s2, &s.c1, &s.d1, &s.f1, s.s3));
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001107 s.Check();
1108
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001109 memset(&s, 'x', sizeof(s));
1110 ASSERT_EQ(9, swscanf(L" hello 123 456abAB! 1.23 0x1.2p3 world",
1111 L"%s %i%i%2c%[A-Z]%c %lf %f %s",
1112 s.s1, &s.i1, &s.i2, s.cs1, s.s2, &s.c1, &s.d1, &s.f1, s.s3));
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001113 s.Check();
Elliott Hughes603332f2014-03-12 17:10:41 -07001114}
Elliott Hughes53b24382014-05-02 18:29:25 -07001115
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001116template <typename T>
1117static void CheckScanf(int sscanf_fn(const T*, const T*, ...),
1118 const T* input, const T* fmt,
1119 int expected_count, const char* expected_string) {
1120 char buf[256] = {};
1121 ASSERT_EQ(expected_count, sscanf_fn(input, fmt, &buf)) << fmt;
1122 ASSERT_STREQ(expected_string, buf) << fmt;
1123}
1124
1125TEST(STDIO_TEST, sscanf_ccl) {
1126 // `abc` is just those characters.
1127 CheckScanf(sscanf, "abcd", "%[abc]", 1, "abc");
1128 // `a-c` is the range 'a' .. 'c'.
1129 CheckScanf(sscanf, "abcd", "%[a-c]", 1, "abc");
1130 CheckScanf(sscanf, "-d", "%[a-c]", 0, "");
1131 CheckScanf(sscanf, "ac-bAd", "%[a--c]", 1, "ac-bA");
1132 // `a-c-e` is equivalent to `a-e`.
1133 CheckScanf(sscanf, "abcdefg", "%[a-c-e]", 1, "abcde");
1134 // `e-a` is equivalent to `ae-` (because 'e' > 'a').
1135 CheckScanf(sscanf, "-a-e-b", "%[e-a]", 1, "-a-e-");
1136 // An initial '^' negates the set.
1137 CheckScanf(sscanf, "abcde", "%[^d]", 1, "abc");
1138 CheckScanf(sscanf, "abcdefgh", "%[^c-d]", 1, "ab");
1139 CheckScanf(sscanf, "hgfedcba", "%[^c-d]", 1, "hgfe");
1140 // The first character may be ']' or '-' without being special.
1141 CheckScanf(sscanf, "[[]]x", "%[][]", 1, "[[]]");
1142 CheckScanf(sscanf, "-a-x", "%[-a]", 1, "-a-");
1143 // The last character may be '-' without being special.
1144 CheckScanf(sscanf, "-a-x", "%[a-]", 1, "-a-");
1145 // X--Y is [X--] + Y, not [X--] + [--Y] (a bug in my initial implementation).
1146 CheckScanf(sscanf, "+,-/.", "%[+--/]", 1, "+,-/");
1147}
1148
1149TEST(STDIO_TEST, swscanf_ccl) {
1150 // `abc` is just those characters.
1151 CheckScanf(swscanf, L"abcd", L"%[abc]", 1, "abc");
1152 // `a-c` is the range 'a' .. 'c'.
1153 CheckScanf(swscanf, L"abcd", L"%[a-c]", 1, "abc");
1154 CheckScanf(swscanf, L"-d", L"%[a-c]", 0, "");
1155 CheckScanf(swscanf, L"ac-bAd", L"%[a--c]", 1, "ac-bA");
1156 // `a-c-e` is equivalent to `a-e`.
1157 CheckScanf(swscanf, L"abcdefg", L"%[a-c-e]", 1, "abcde");
1158 // `e-a` is equivalent to `ae-` (because 'e' > 'a').
1159 CheckScanf(swscanf, L"-a-e-b", L"%[e-a]", 1, "-a-e-");
1160 // An initial '^' negates the set.
1161 CheckScanf(swscanf, L"abcde", L"%[^d]", 1, "abc");
1162 CheckScanf(swscanf, L"abcdefgh", L"%[^c-d]", 1, "ab");
1163 CheckScanf(swscanf, L"hgfedcba", L"%[^c-d]", 1, "hgfe");
1164 // The first character may be ']' or '-' without being special.
1165 CheckScanf(swscanf, L"[[]]x", L"%[][]", 1, "[[]]");
1166 CheckScanf(swscanf, L"-a-x", L"%[-a]", 1, "-a-");
1167 // The last character may be '-' without being special.
1168 CheckScanf(swscanf, L"-a-x", L"%[a-]", 1, "-a-");
1169 // X--Y is [X--] + Y, not [X--] + [--Y] (a bug in my initial implementation).
1170 CheckScanf(swscanf, L"+,-/.", L"%[+--/]", 1, "+,-/");
1171}
1172
Elliott Hughes38e4aef2018-01-18 10:21:29 -08001173template <typename T1, typename T2>
1174static void CheckScanfM(int sscanf_fn(const T1*, const T1*, ...),
1175 const T1* input, const T1* fmt,
1176 int expected_count, const T2* expected_string) {
1177 T2* result = nullptr;
1178 ASSERT_EQ(expected_count, sscanf_fn(input, fmt, &result)) << fmt;
1179 if (expected_string == nullptr) {
1180 ASSERT_EQ(nullptr, result);
1181 } else {
1182 ASSERT_STREQ(expected_string, result) << fmt;
1183 }
1184 free(result);
1185}
1186
1187TEST(STDIO_TEST, sscanf_mc) {
1188 char* p1 = nullptr;
1189 char* p2 = nullptr;
1190 ASSERT_EQ(2, sscanf("hello", "%mc%mc", &p1, &p2));
1191 ASSERT_EQ('h', *p1);
1192 ASSERT_EQ('e', *p2);
1193 free(p1);
1194 free(p2);
1195
1196 p1 = nullptr;
1197 ASSERT_EQ(1, sscanf("hello", "%4mc", &p1));
1198 ASSERT_EQ('h', p1[0]);
1199 ASSERT_EQ('e', p1[1]);
1200 ASSERT_EQ('l', p1[2]);
1201 ASSERT_EQ('l', p1[3]);
1202 free(p1);
1203
1204 p1 = nullptr;
1205 ASSERT_EQ(1, sscanf("hello world", "%30mc", &p1));
1206 ASSERT_EQ('h', p1[0]);
1207 ASSERT_EQ('e', p1[1]);
1208 ASSERT_EQ('l', p1[2]);
1209 ASSERT_EQ('l', p1[3]);
1210 ASSERT_EQ('o', p1[4]);
1211 free(p1);
1212}
1213
Elliott Hughes38e4aef2018-01-18 10:21:29 -08001214TEST(STDIO_TEST, sscanf_mlc) {
1215 // This is so useless that clang doesn't even believe it exists...
1216#pragma clang diagnostic push
1217#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
1218#pragma clang diagnostic ignored "-Wformat-extra-args"
1219
1220 wchar_t* p1 = nullptr;
1221 wchar_t* p2 = nullptr;
1222 ASSERT_EQ(2, sscanf("hello", "%mlc%mlc", &p1, &p2));
1223 ASSERT_EQ(L'h', *p1);
1224 ASSERT_EQ(L'e', *p2);
1225 free(p1);
1226 free(p2);
1227
1228 p1 = nullptr;
1229 ASSERT_EQ(1, sscanf("hello", "%4mlc", &p1));
1230 ASSERT_EQ(L'h', p1[0]);
1231 ASSERT_EQ(L'e', p1[1]);
1232 ASSERT_EQ(L'l', p1[2]);
1233 ASSERT_EQ(L'l', p1[3]);
1234 free(p1);
1235
1236 p1 = nullptr;
1237 ASSERT_EQ(1, sscanf("hello world", "%30mlc", &p1));
1238 ASSERT_EQ(L'h', p1[0]);
1239 ASSERT_EQ(L'e', p1[1]);
1240 ASSERT_EQ(L'l', p1[2]);
1241 ASSERT_EQ(L'l', p1[3]);
1242 ASSERT_EQ(L'o', p1[4]);
1243 free(p1);
1244#pragma clang diagnostic pop
1245}
1246
Elliott Hughes38e4aef2018-01-18 10:21:29 -08001247TEST(STDIO_TEST, sscanf_ms) {
1248 CheckScanfM(sscanf, "hello", "%ms", 1, "hello");
1249 CheckScanfM(sscanf, "hello", "%4ms", 1, "hell");
1250 CheckScanfM(sscanf, "hello world", "%30ms", 1, "hello");
1251}
1252
1253TEST(STDIO_TEST, sscanf_mls) {
1254 CheckScanfM(sscanf, "hello", "%mls", 1, L"hello");
1255 CheckScanfM(sscanf, "hello", "%4mls", 1, L"hell");
1256 CheckScanfM(sscanf, "hello world", "%30mls", 1, L"hello");
1257}
1258
1259TEST(STDIO_TEST, sscanf_m_ccl) {
1260 CheckScanfM(sscanf, "hello", "%m[a-z]", 1, "hello");
1261 CheckScanfM(sscanf, "hello", "%4m[a-z]", 1, "hell");
1262 CheckScanfM(sscanf, "hello world", "%30m[a-z]", 1, "hello");
1263}
1264
1265TEST(STDIO_TEST, sscanf_ml_ccl) {
1266 CheckScanfM(sscanf, "hello", "%ml[a-z]", 1, L"hello");
1267 CheckScanfM(sscanf, "hello", "%4ml[a-z]", 1, L"hell");
1268 CheckScanfM(sscanf, "hello world", "%30ml[a-z]", 1, L"hello");
1269}
1270
1271TEST(STDIO_TEST, sscanf_ls) {
1272 wchar_t w[32] = {};
1273 ASSERT_EQ(1, sscanf("hello world", "%ls", w));
1274 ASSERT_EQ(L"hello", std::wstring(w));
1275}
1276
1277TEST(STDIO_TEST, sscanf_ls_suppress) {
1278 ASSERT_EQ(0, sscanf("hello world", "%*ls %*ls"));
1279}
1280
1281TEST(STDIO_TEST, sscanf_ls_n) {
1282 setlocale(LC_ALL, "C.UTF-8");
1283 wchar_t w[32] = {};
1284 int pos = 0;
1285 ASSERT_EQ(1, sscanf("\xc4\x80", "%ls%n", w, &pos));
1286 ASSERT_EQ(static_cast<wchar_t>(256), w[0]);
1287 ASSERT_EQ(2, pos);
1288}
1289
1290TEST(STDIO_TEST, sscanf_ls_realloc) {
1291 // This is so useless that clang doesn't even believe it exists...
1292#pragma clang diagnostic push
1293#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
1294#pragma clang diagnostic ignored "-Wformat-extra-args"
1295 wchar_t* p1 = nullptr;
1296 wchar_t* p2 = nullptr;
1297 ASSERT_EQ(2, sscanf("1234567890123456789012345678901234567890 world", "%mls %mls", &p1, &p2));
1298 ASSERT_EQ(L"1234567890123456789012345678901234567890", std::wstring(p1));
1299 ASSERT_EQ(L"world", std::wstring(p2));
1300#pragma clang diagnostic pop
1301}
1302
Elliott Hughesbf9cb9e2017-12-11 12:39:01 -08001303// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=202240
1304TEST(STDIO_TEST, scanf_wscanf_EOF) {
1305 EXPECT_EQ(0, sscanf("b", "ab"));
1306 EXPECT_EQ(EOF, sscanf("", "a"));
1307 EXPECT_EQ(0, swscanf(L"b", L"ab"));
1308 EXPECT_EQ(EOF, swscanf(L"", L"a"));
1309}
1310
1311TEST(STDIO_TEST, scanf_invalid_UTF8) {
1312#if 0 // TODO: more tests invented during code review; no regressions, so fix later.
1313 char buf[BUFSIZ];
1314 wchar_t wbuf[BUFSIZ];
1315
1316 memset(buf, 0, sizeof(buf));
1317 memset(wbuf, 0, sizeof(wbuf));
1318 EXPECT_EQ(0, sscanf("\xc0" " foo", "%ls %s", wbuf, buf));
1319#endif
1320}
1321
1322TEST(STDIO_TEST, scanf_no_match_no_termination) {
1323 char buf[4] = "x";
1324 EXPECT_EQ(0, sscanf("d", "%[abc]", buf));
1325 EXPECT_EQ('x', buf[0]);
1326 EXPECT_EQ(0, swscanf(L"d", L"%[abc]", buf));
1327 EXPECT_EQ('x', buf[0]);
1328
1329 wchar_t wbuf[4] = L"x";
1330 EXPECT_EQ(0, swscanf(L"d", L"%l[abc]", wbuf));
1331 EXPECT_EQ(L'x', wbuf[0]);
1332
1333 EXPECT_EQ(EOF, sscanf("", "%s", buf));
1334 EXPECT_EQ('x', buf[0]);
1335
1336 EXPECT_EQ(EOF, swscanf(L"", L"%ls", wbuf));
1337 EXPECT_EQ(L'x', wbuf[0]);
1338}
1339
1340TEST(STDIO_TEST, scanf_wscanf_wide_character_class) {
1341#if 0 // TODO: more tests invented during code review; no regressions, so fix later.
1342 wchar_t buf[BUFSIZ];
1343
1344 // A wide character shouldn't match an ASCII-only class for scanf or wscanf.
1345 memset(buf, 0, sizeof(buf));
1346 EXPECT_EQ(1, sscanf("xĀyz", "%l[xy]", buf));
1347 EXPECT_EQ(L"x"s, std::wstring(buf));
1348 memset(buf, 0, sizeof(buf));
1349 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[xy]", buf));
1350 EXPECT_EQ(L"x"s, std::wstring(buf));
1351
1352 // Even if scanf has wide characters in a class, they won't match...
1353 // TODO: is that a bug?
1354 memset(buf, 0, sizeof(buf));
1355 EXPECT_EQ(1, sscanf("xĀyz", "%l[xĀy]", buf));
1356 EXPECT_EQ(L"x"s, std::wstring(buf));
1357 // ...unless you use wscanf.
1358 memset(buf, 0, sizeof(buf));
1359 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[xĀy]", buf));
1360 EXPECT_EQ(L"xĀy"s, std::wstring(buf));
1361
1362 // Negation only covers ASCII for scanf...
1363 memset(buf, 0, sizeof(buf));
1364 EXPECT_EQ(1, sscanf("xĀyz", "%l[^ab]", buf));
1365 EXPECT_EQ(L"x"s, std::wstring(buf));
1366 // ...but covers wide characters for wscanf.
1367 memset(buf, 0, sizeof(buf));
1368 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[^ab]", buf));
1369 EXPECT_EQ(L"xĀyz"s, std::wstring(buf));
1370
1371 // We already determined that non-ASCII characters are ignored in scanf classes.
1372 memset(buf, 0, sizeof(buf));
1373 EXPECT_EQ(1, sscanf("x"
1374 "\xc4\x80" // Matches a byte from each wide char in the class.
1375 "\xc6\x82" // Neither byte is in the class.
1376 "yz",
1377 "%l[xy" "\xc5\x80" "\xc4\x81" "]", buf));
1378 EXPECT_EQ(L"x", std::wstring(buf));
1379 // bionic and glibc both behave badly for wscanf, so let's call it right for now...
1380 memset(buf, 0, sizeof(buf));
1381 EXPECT_EQ(1, swscanf(L"x"
1382 L"\xc4\x80"
1383 L"\xc6\x82"
1384 L"yz",
1385 L"%l[xy" L"\xc5\x80" L"\xc4\x81" L"]", buf));
1386 // Note that this isn't L"xĀ" --- although the *bytes* matched, they're
1387 // not put back together as a wide character.
1388 EXPECT_EQ(L"x" L"\xc4" L"\x80", std::wstring(buf));
1389#endif
1390}
1391
Christopher Ferris13f26a72016-01-13 13:47:58 -08001392TEST(STDIO_TEST, cantwrite_EBADF) {
Elliott Hughes53b24382014-05-02 18:29:25 -07001393 // If we open a file read-only...
1394 FILE* fp = fopen("/proc/version", "r");
1395
1396 // ...all attempts to write to that file should return failure.
1397
1398 // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
1399 // glibc gets the wide-character functions wrong.
1400
1401 errno = 0;
1402 EXPECT_EQ(EOF, putc('x', fp));
1403 EXPECT_EQ(EBADF, errno);
1404
1405 errno = 0;
1406 EXPECT_EQ(EOF, fprintf(fp, "hello"));
1407 EXPECT_EQ(EBADF, errno);
1408
1409 errno = 0;
1410 EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
Elliott Hughes063525c2014-05-13 11:19:57 -07001411#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -07001412 EXPECT_EQ(EBADF, errno);
1413#endif
1414
1415 errno = 0;
Elliott Hughes53b24382014-05-02 18:29:25 -07001416 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
1417 EXPECT_EQ(EBADF, errno);
1418
1419 errno = 0;
1420 EXPECT_EQ(EOF, fputs("hello", fp));
1421 EXPECT_EQ(EBADF, errno);
1422
1423 errno = 0;
1424 EXPECT_EQ(WEOF, fputwc(L'x', fp));
Elliott Hughes063525c2014-05-13 11:19:57 -07001425#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -07001426 EXPECT_EQ(EBADF, errno);
1427#endif
1428}
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001429
1430// Tests that we can only have a consistent and correct fpos_t when using
1431// f*pos functions (i.e. fpos doesn't get inside a multi byte character).
Christopher Ferris13f26a72016-01-13 13:47:58 -08001432TEST(STDIO_TEST, consistent_fpos_t) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001433 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
1434 uselocale(LC_GLOBAL_LOCALE);
1435
1436 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -07001437 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001438
1439 wchar_t mb_one_bytes = L'h';
1440 wchar_t mb_two_bytes = 0x00a2;
1441 wchar_t mb_three_bytes = 0x20ac;
1442 wchar_t mb_four_bytes = 0x24b62;
1443
1444 // Write to file.
1445 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp)));
1446 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
1447 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
1448 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
1449
1450 rewind(fp);
1451
1452 // Record each character position.
1453 fpos_t pos1;
1454 fpos_t pos2;
1455 fpos_t pos3;
1456 fpos_t pos4;
1457 fpos_t pos5;
1458 EXPECT_EQ(0, fgetpos(fp, &pos1));
1459 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
1460 EXPECT_EQ(0, fgetpos(fp, &pos2));
1461 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1462 EXPECT_EQ(0, fgetpos(fp, &pos3));
1463 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
1464 EXPECT_EQ(0, fgetpos(fp, &pos4));
1465 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
1466 EXPECT_EQ(0, fgetpos(fp, &pos5));
1467
Elliott Hughes063525c2014-05-13 11:19:57 -07001468#if defined(__BIONIC__)
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001469 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD
1470 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In
1471 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE
1472 // structure.
1473 ASSERT_EQ(0, static_cast<off_t>(pos1));
1474 ASSERT_EQ(1, static_cast<off_t>(pos2));
1475 ASSERT_EQ(3, static_cast<off_t>(pos3));
1476 ASSERT_EQ(6, static_cast<off_t>(pos4));
1477 ASSERT_EQ(10, static_cast<off_t>(pos5));
1478#endif
1479
1480 // Exercise back and forth movements of the position.
1481 ASSERT_EQ(0, fsetpos(fp, &pos2));
1482 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1483 ASSERT_EQ(0, fsetpos(fp, &pos1));
1484 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
1485 ASSERT_EQ(0, fsetpos(fp, &pos4));
1486 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
1487 ASSERT_EQ(0, fsetpos(fp, &pos3));
1488 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
1489 ASSERT_EQ(0, fsetpos(fp, &pos5));
1490 ASSERT_EQ(WEOF, fgetwc(fp));
1491
1492 fclose(fp);
1493}
1494
1495// Exercise the interaction between fpos and seek.
Christopher Ferris13f26a72016-01-13 13:47:58 -08001496TEST(STDIO_TEST, fpos_t_and_seek) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001497 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
1498 uselocale(LC_GLOBAL_LOCALE);
1499
Calin Juravle9b95ea92014-05-14 17:07:10 +01001500 // In glibc-2.16 fseek doesn't work properly in wide mode
1501 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is
1502 // to close and re-open the file. We do it in order to make the test pass
1503 // with all glibcs.
1504
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001505 TemporaryFile tf;
1506 FILE* fp = fdopen(tf.fd, "w+");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001507 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001508
1509 wchar_t mb_two_bytes = 0x00a2;
1510 wchar_t mb_three_bytes = 0x20ac;
1511 wchar_t mb_four_bytes = 0x24b62;
1512
1513 // Write to file.
1514 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
1515 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
1516 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
1517
1518 fflush(fp);
1519 fclose(fp);
1520
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08001521 fp = fopen(tf.path, "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001522 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001523
1524 // Store a valid position.
1525 fpos_t mb_two_bytes_pos;
1526 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos));
1527
1528 // Move inside mb_four_bytes with fseek.
1529 long offset_inside_mb = 6;
1530 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET));
1531
1532 // Store the "inside multi byte" position.
1533 fpos_t pos_inside_mb;
1534 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb));
Elliott Hughes063525c2014-05-13 11:19:57 -07001535#if defined(__BIONIC__)
1536 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb));
1537#endif
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001538
1539 // Reading from within a byte should produce an error.
1540 ASSERT_EQ(WEOF, fgetwc(fp));
1541 ASSERT_EQ(EILSEQ, errno);
1542
1543 // Reverting to a valid position should work.
1544 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos));
1545 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1546
1547 // Moving withing a multi byte with fsetpos should work but reading should
1548 // produce an error.
1549 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb));
1550 ASSERT_EQ(WEOF, fgetwc(fp));
1551 ASSERT_EQ(EILSEQ, errno);
1552
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001553 ASSERT_EQ(0, fclose(fp));
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001554}
Elliott Hughes6b841db2014-08-20 16:10:49 -07001555
Christopher Ferris13f26a72016-01-13 13:47:58 -08001556TEST(STDIO_TEST, fmemopen) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001557 char buf[16];
1558 memset(buf, 0, sizeof(buf));
1559 FILE* fp = fmemopen(buf, sizeof(buf), "r+");
1560 ASSERT_EQ('<', fputc('<', fp));
1561 ASSERT_NE(EOF, fputs("abc>\n", fp));
1562 fflush(fp);
1563
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001564 // We wrote to the buffer...
Elliott Hughes6b841db2014-08-20 16:10:49 -07001565 ASSERT_STREQ("<abc>\n", buf);
1566
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001567 // And can read back from the file.
Elliott Hughes70715da2016-08-01 16:35:17 -07001568 AssertFileIs(fp, "<abc>\n", true);
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001569 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001570}
1571
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001572TEST(STDIO_TEST, fmemopen_nullptr) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001573 FILE* fp = fmemopen(nullptr, 128, "r+");
1574 ASSERT_NE(EOF, fputs("xyz\n", fp));
1575
Elliott Hughes70715da2016-08-01 16:35:17 -07001576 AssertFileIs(fp, "xyz\n", true);
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001577 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001578}
1579
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001580TEST(STDIO_TEST, fmemopen_trailing_NUL_byte) {
1581 FILE* fp;
1582 char buf[8];
1583
1584 // POSIX: "When a stream open for writing is flushed or closed, a null byte
1585 // shall be written at the current position or at the end of the buffer,
1586 // depending on the size of the contents."
1587 memset(buf, 'x', sizeof(buf));
1588 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w"));
1589 // Even with nothing written (and not in truncate mode), we'll flush a NUL...
1590 ASSERT_EQ(0, fflush(fp));
1591 EXPECT_EQ("\0xxxxxxx"s, std::string(buf, buf + sizeof(buf)));
1592 // Now write and check that the NUL moves along with our writes...
1593 ASSERT_NE(EOF, fputs("hello", fp));
1594 ASSERT_EQ(0, fflush(fp));
1595 EXPECT_EQ("hello\0xx"s, std::string(buf, buf + sizeof(buf)));
1596 ASSERT_NE(EOF, fputs("wo", fp));
1597 ASSERT_EQ(0, fflush(fp));
1598 EXPECT_EQ("hellowo\0"s, std::string(buf, buf + sizeof(buf)));
1599 ASSERT_EQ(0, fclose(fp));
1600
1601 // "If a stream open for update is flushed or closed and the last write has
1602 // advanced the current buffer size, a null byte shall be written at the end
1603 // of the buffer if it fits."
1604 memset(buf, 'x', sizeof(buf));
1605 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r+"));
1606 // Nothing written yet, so no advance...
1607 ASSERT_EQ(0, fflush(fp));
1608 EXPECT_EQ("xxxxxxxx"s, std::string(buf, buf + sizeof(buf)));
1609 ASSERT_NE(EOF, fputs("hello", fp));
1610 ASSERT_EQ(0, fclose(fp));
1611}
1612
1613TEST(STDIO_TEST, fmemopen_size) {
1614 FILE* fp;
Elliott Hughes6b841db2014-08-20 16:10:49 -07001615 char buf[16];
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001616 memset(buf, 'x', sizeof(buf));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001617
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001618 // POSIX: "The stream shall also maintain the size of the current buffer
1619 // contents; use of fseek() or fseeko() on the stream with SEEK_END shall
1620 // seek relative to this size."
Elliott Hughes6b841db2014-08-20 16:10:49 -07001621
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001622 // "For modes r and r+ the size shall be set to the value given by the size
1623 // argument."
1624 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "r"));
1625 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1626 EXPECT_EQ(16, ftell(fp));
1627 EXPECT_EQ(16, ftello(fp));
1628 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1629 EXPECT_EQ(16, ftell(fp));
1630 EXPECT_EQ(16, ftello(fp));
1631 ASSERT_EQ(0, fclose(fp));
1632 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "r+"));
1633 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1634 EXPECT_EQ(16, ftell(fp));
1635 EXPECT_EQ(16, ftello(fp));
1636 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1637 EXPECT_EQ(16, ftell(fp));
1638 EXPECT_EQ(16, ftello(fp));
1639 ASSERT_EQ(0, fclose(fp));
1640
1641 // "For modes w and w+ the initial size shall be zero..."
1642 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w"));
1643 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1644 EXPECT_EQ(0, ftell(fp));
1645 EXPECT_EQ(0, ftello(fp));
1646 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1647 EXPECT_EQ(0, ftell(fp));
1648 EXPECT_EQ(0, ftello(fp));
1649 ASSERT_EQ(0, fclose(fp));
1650 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w+"));
1651 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1652 EXPECT_EQ(0, ftell(fp));
1653 EXPECT_EQ(0, ftello(fp));
1654 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1655 EXPECT_EQ(0, ftell(fp));
1656 EXPECT_EQ(0, ftello(fp));
1657 ASSERT_EQ(0, fclose(fp));
1658
1659 // "...and for modes a and a+ the initial size shall be:
1660 // 1. Zero, if buf is a null pointer
1661 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "a"));
1662 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1663 EXPECT_EQ(0, ftell(fp));
1664 EXPECT_EQ(0, ftello(fp));
1665 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1666 EXPECT_EQ(0, ftell(fp));
1667 EXPECT_EQ(0, ftello(fp));
1668 ASSERT_EQ(0, fclose(fp));
1669 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "a+"));
1670 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1671 EXPECT_EQ(0, ftell(fp));
1672 EXPECT_EQ(0, ftello(fp));
1673 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1674 EXPECT_EQ(0, ftell(fp));
1675 EXPECT_EQ(0, ftello(fp));
1676 ASSERT_EQ(0, fclose(fp));
1677
1678 // 2. The position of the first null byte in the buffer, if one is found
1679 memset(buf, 'x', sizeof(buf));
1680 buf[3] = '\0';
1681 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a"));
1682 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1683 EXPECT_EQ(3, ftell(fp));
1684 EXPECT_EQ(3, ftello(fp));
1685 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1686 EXPECT_EQ(3, ftell(fp));
1687 EXPECT_EQ(3, ftello(fp));
1688 ASSERT_EQ(0, fclose(fp));
1689 memset(buf, 'x', sizeof(buf));
1690 buf[3] = '\0';
1691 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a+"));
1692 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1693 EXPECT_EQ(3, ftell(fp));
1694 EXPECT_EQ(3, ftello(fp));
1695 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1696 EXPECT_EQ(3, ftell(fp));
1697 EXPECT_EQ(3, ftello(fp));
1698 ASSERT_EQ(0, fclose(fp));
1699
1700 // 3. The value of the size argument, if buf is not a null pointer and no
1701 // null byte is found.
1702 memset(buf, 'x', sizeof(buf));
1703 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a"));
1704 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1705 EXPECT_EQ(16, ftell(fp));
1706 EXPECT_EQ(16, ftello(fp));
1707 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1708 EXPECT_EQ(16, ftell(fp));
1709 EXPECT_EQ(16, ftello(fp));
1710 ASSERT_EQ(0, fclose(fp));
1711 memset(buf, 'x', sizeof(buf));
1712 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a+"));
1713 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1714 EXPECT_EQ(16, ftell(fp));
1715 EXPECT_EQ(16, ftello(fp));
1716 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1717 EXPECT_EQ(16, ftell(fp));
1718 EXPECT_EQ(16, ftello(fp));
1719 ASSERT_EQ(0, fclose(fp));
1720}
1721
1722TEST(STDIO_TEST, fmemopen_SEEK_END) {
1723 // fseek SEEK_END is relative to the current string length, not the buffer size.
1724 FILE* fp;
1725 char buf[8];
1726 memset(buf, 'x', sizeof(buf));
1727 strcpy(buf, "str");
1728 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1729 ASSERT_NE(EOF, fputs("string", fp));
1730 EXPECT_EQ(0, fseek(fp, 0, SEEK_END));
1731 EXPECT_EQ(static_cast<long>(strlen("string")), ftell(fp));
1732 EXPECT_EQ(static_cast<off_t>(strlen("string")), ftello(fp));
1733 EXPECT_EQ(0, fclose(fp));
1734
1735 // glibc < 2.22 interpreted SEEK_END the wrong way round (subtracting rather
1736 // than adding).
1737 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1738 ASSERT_NE(EOF, fputs("54321", fp));
1739 EXPECT_EQ(0, fseek(fp, -2, SEEK_END));
1740 EXPECT_EQ('2', fgetc(fp));
1741 EXPECT_EQ(0, fclose(fp));
1742}
1743
1744TEST(STDIO_TEST, fmemopen_seek_invalid) {
1745 char buf[8];
1746 memset(buf, 'x', sizeof(buf));
1747 FILE* fp = fmemopen(buf, sizeof(buf), "w");
1748 ASSERT_TRUE(fp != nullptr);
1749
1750 // POSIX: "An attempt to seek ... to a negative position or to a position
1751 // larger than the buffer size given in the size argument shall fail."
1752 // (There's no mention of what errno should be set to, and glibc doesn't
1753 // set errno in any of these cases.)
1754 EXPECT_EQ(-1, fseek(fp, -2, SEEK_SET));
1755 EXPECT_EQ(-1, fseeko(fp, -2, SEEK_SET));
1756 EXPECT_EQ(-1, fseek(fp, sizeof(buf) + 1, SEEK_SET));
1757 EXPECT_EQ(-1, fseeko(fp, sizeof(buf) + 1, SEEK_SET));
1758}
1759
1760TEST(STDIO_TEST, fmemopen_read_EOF) {
1761 // POSIX: "A read operation on the stream shall not advance the current
1762 // buffer position beyond the current buffer size."
1763 char buf[8];
1764 memset(buf, 'x', sizeof(buf));
1765 FILE* fp = fmemopen(buf, sizeof(buf), "r");
1766 ASSERT_TRUE(fp != nullptr);
1767 char buf2[BUFSIZ];
1768 ASSERT_EQ(8U, fread(buf2, 1, sizeof(buf2), fp));
1769 // POSIX: "Reaching the buffer size in a read operation shall count as
1770 // end-of-file.
1771 ASSERT_TRUE(feof(fp));
1772 ASSERT_EQ(EOF, fgetc(fp));
1773 ASSERT_EQ(0, fclose(fp));
1774}
1775
1776TEST(STDIO_TEST, fmemopen_read_null_bytes) {
1777 // POSIX: "Null bytes in the buffer shall have no special meaning for reads."
1778 char buf[] = "h\0e\0l\0l\0o";
1779 FILE* fp = fmemopen(buf, sizeof(buf), "r");
1780 ASSERT_TRUE(fp != nullptr);
1781 ASSERT_EQ('h', fgetc(fp));
1782 ASSERT_EQ(0, fgetc(fp));
1783 ASSERT_EQ('e', fgetc(fp));
1784 ASSERT_EQ(0, fgetc(fp));
1785 ASSERT_EQ('l', fgetc(fp));
1786 ASSERT_EQ(0, fgetc(fp));
1787 // POSIX: "The read operation shall start at the current buffer position of
1788 // the stream."
1789 char buf2[8];
1790 memset(buf2, 'x', sizeof(buf2));
1791 ASSERT_EQ(4U, fread(buf2, 1, sizeof(buf2), fp));
1792 ASSERT_EQ('l', buf2[0]);
1793 ASSERT_EQ(0, buf2[1]);
1794 ASSERT_EQ('o', buf2[2]);
1795 ASSERT_EQ(0, buf2[3]);
1796 for (size_t i = 4; i < sizeof(buf2); ++i) ASSERT_EQ('x', buf2[i]) << i;
1797 ASSERT_TRUE(feof(fp));
1798 ASSERT_EQ(0, fclose(fp));
1799}
1800
1801TEST(STDIO_TEST, fmemopen_write) {
1802 FILE* fp;
1803 char buf[8];
1804
1805 // POSIX: "A write operation shall start either at the current position of
1806 // the stream (if mode has not specified 'a' as the first character)..."
1807 memset(buf, 'x', sizeof(buf));
1808 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r+"));
1809 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1810 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
1811 ASSERT_EQ(' ', fputc(' ', fp));
1812 EXPECT_EQ("xx xxxxx", std::string(buf, buf + sizeof(buf)));
1813 ASSERT_EQ(0, fclose(fp));
1814
1815 // "...or at the current size of the stream (if mode had 'a' as the first
1816 // character)." (See the fmemopen_size test for what "size" means, but for
1817 // mode "a", it's the first NUL byte.)
1818 memset(buf, 'x', sizeof(buf));
1819 buf[3] = '\0';
1820 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a+"));
1821 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1822 ASSERT_EQ(' ', fputc(' ', fp));
1823 EXPECT_EQ("xxx \0xxx"s, std::string(buf, buf + sizeof(buf)));
1824 ASSERT_EQ(0, fclose(fp));
1825
1826 // "If the current position at the end of the write is larger than the
1827 // current buffer size, the current buffer size shall be set to the current
1828 // position." (See the fmemopen_size test for what "size" means, but to
1829 // query it we SEEK_END with offset 0, and then ftell.)
1830 memset(buf, 'x', sizeof(buf));
1831 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1832 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1833 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1834 EXPECT_EQ(0, ftell(fp));
1835 ASSERT_EQ(' ', fputc(' ', fp));
1836 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1837 EXPECT_EQ(1, ftell(fp));
1838 ASSERT_NE(EOF, fputs("123", fp));
1839 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1840 EXPECT_EQ(4, ftell(fp));
1841 EXPECT_EQ(" 123\0xxx"s, std::string(buf, buf + sizeof(buf)));
1842 ASSERT_EQ(0, fclose(fp));
1843}
1844
1845TEST(STDIO_TEST, fmemopen_write_EOF) {
1846 // POSIX: "A write operation on the stream shall not advance the current
1847 // buffer size beyond the size given in the size argument."
1848 FILE* fp;
1849
1850 // Scalar writes...
1851 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 4, "w"));
1852 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1853 ASSERT_EQ('x', fputc('x', fp));
1854 ASSERT_EQ('x', fputc('x', fp));
1855 ASSERT_EQ('x', fputc('x', fp));
1856 ASSERT_EQ(EOF, fputc('x', fp)); // Only 3 fit because of the implicit NUL.
1857 ASSERT_EQ(0, fclose(fp));
1858
1859 // Vector writes...
1860 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 4, "w"));
1861 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1862 ASSERT_EQ(3U, fwrite("xxxx", 1, 4, fp));
1863 ASSERT_EQ(0, fclose(fp));
1864}
1865
1866TEST(STDIO_TEST, fmemopen_initial_position) {
1867 // POSIX: "The ... current position in the buffer ... shall be initially
1868 // set to either the beginning of the buffer (for r and w modes) ..."
1869 char buf[] = "hello\0world";
1870 FILE* fp;
1871 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r"));
1872 EXPECT_EQ(0L, ftell(fp));
1873 EXPECT_EQ(0, fclose(fp));
1874 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w"));
1875 EXPECT_EQ(0L, ftell(fp));
1876 EXPECT_EQ(0, fclose(fp));
1877 buf[0] = 'h'; // (Undo the effects of the above.)
1878
1879 // POSIX: "...or to the first null byte in the buffer (for a modes)."
1880 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1881 EXPECT_EQ(5L, ftell(fp));
1882 EXPECT_EQ(0, fclose(fp));
1883
1884 // POSIX: "If no null byte is found in append mode, the initial position
1885 // shall be set to one byte after the end of the buffer."
1886 memset(buf, 'x', sizeof(buf));
1887 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1888 EXPECT_EQ(static_cast<long>(sizeof(buf)), ftell(fp));
1889 EXPECT_EQ(0, fclose(fp));
1890}
1891
1892TEST(STDIO_TEST, fmemopen_initial_position_allocated) {
1893 // POSIX: "If buf is a null pointer, the initial position shall always be
1894 // set to the beginning of the buffer."
1895 FILE* fp = fmemopen(nullptr, 128, "a+");
1896 ASSERT_TRUE(fp != nullptr);
1897 EXPECT_EQ(0L, ftell(fp));
1898 EXPECT_EQ(0L, fseek(fp, 0, SEEK_SET));
1899 EXPECT_EQ(0, fclose(fp));
1900}
1901
1902TEST(STDIO_TEST, fmemopen_zero_length) {
1903 // POSIX says it's up to the implementation whether or not you can have a
1904 // zero-length buffer (but "A future version of this standard may require
1905 // support of zero-length buffer streams explicitly"). BSD and glibc < 2.22
1906 // agreed that you couldn't, but glibc >= 2.22 allows it for consistency.
1907 FILE* fp;
1908 char buf[16];
1909 ASSERT_NE(nullptr, fp = fmemopen(buf, 0, "r+"));
1910 ASSERT_EQ(EOF, fgetc(fp));
1911 ASSERT_TRUE(feof(fp));
1912 ASSERT_EQ(0, fclose(fp));
1913 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 0, "r+"));
1914 ASSERT_EQ(EOF, fgetc(fp));
1915 ASSERT_TRUE(feof(fp));
1916 ASSERT_EQ(0, fclose(fp));
1917
1918 ASSERT_NE(nullptr, fp = fmemopen(buf, 0, "w+"));
1919 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1920 ASSERT_EQ(EOF, fputc('x', fp));
1921 ASSERT_EQ(0, fclose(fp));
1922 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 0, "w+"));
1923 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1924 ASSERT_EQ(EOF, fputc('x', fp));
1925 ASSERT_EQ(0, fclose(fp));
1926}
1927
Elliott Hughes288465d2019-02-05 15:00:13 -08001928TEST(STDIO_TEST, fmemopen_zero_length_buffer_overrun) {
1929 char buf[2] = "x";
1930 ASSERT_EQ('x', buf[0]);
1931 FILE* fp = fmemopen(buf, 0, "w");
1932 ASSERT_EQ('x', buf[0]);
1933 ASSERT_EQ(0, fclose(fp));
1934}
1935
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001936TEST(STDIO_TEST, fmemopen_write_only_allocated) {
1937 // POSIX says fmemopen "may fail if the mode argument does not include a '+'".
1938 // BSD fails, glibc doesn't. We side with the more lenient.
1939 FILE* fp;
1940 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "r"));
1941 ASSERT_EQ(0, fclose(fp));
1942 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w"));
1943 ASSERT_EQ(0, fclose(fp));
1944}
1945
1946TEST(STDIO_TEST, fmemopen_fileno) {
1947 // There's no fd backing an fmemopen FILE*.
1948 FILE* fp = fmemopen(nullptr, 16, "r");
1949 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b841db2014-08-20 16:10:49 -07001950 errno = 0;
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001951 ASSERT_EQ(-1, fileno(fp));
1952 ASSERT_EQ(EBADF, errno);
1953 ASSERT_EQ(0, fclose(fp));
1954}
1955
1956TEST(STDIO_TEST, fmemopen_append_after_seek) {
1957 // In BSD and glibc < 2.22, append mode didn't force writes to append if
1958 // there had been an intervening seek.
1959
1960 FILE* fp;
1961 char buf[] = "hello\0world";
1962 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1963 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1964 ASSERT_EQ(0, fseek(fp, 0, SEEK_SET));
1965 ASSERT_NE(EOF, fputc('!', fp));
1966 EXPECT_EQ("hello!\0orld\0"s, std::string(buf, buf + sizeof(buf)));
1967 ASSERT_EQ(0, fclose(fp));
1968
1969 memcpy(buf, "hello\0world", sizeof(buf));
1970 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a+"));
1971 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1972 ASSERT_EQ(0, fseek(fp, 0, SEEK_SET));
1973 ASSERT_NE(EOF, fputc('!', fp));
1974 EXPECT_EQ("hello!\0orld\0"s, std::string(buf, buf + sizeof(buf)));
1975 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001976}
1977
Christopher Ferris13f26a72016-01-13 13:47:58 -08001978TEST(STDIO_TEST, open_memstream) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001979 char* p = nullptr;
1980 size_t size = 0;
1981 FILE* fp = open_memstream(&p, &size);
1982 ASSERT_NE(EOF, fputs("hello, world!", fp));
1983 fclose(fp);
1984
1985 ASSERT_STREQ("hello, world!", p);
1986 ASSERT_EQ(strlen("hello, world!"), size);
1987 free(p);
1988}
1989
Christopher Ferris13f26a72016-01-13 13:47:58 -08001990TEST(STDIO_TEST, open_memstream_EINVAL) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001991#if defined(__BIONIC__)
zijunzhao00a3dba2023-03-01 00:07:40 +00001992#pragma clang diagnostic push
1993#pragma clang diagnostic ignored "-Wnonnull"
Elliott Hughes6b841db2014-08-20 16:10:49 -07001994 char* p;
1995 size_t size;
1996
1997 // Invalid buffer.
1998 errno = 0;
1999 ASSERT_EQ(nullptr, open_memstream(nullptr, &size));
2000 ASSERT_EQ(EINVAL, errno);
2001
2002 // Invalid size.
2003 errno = 0;
2004 ASSERT_EQ(nullptr, open_memstream(&p, nullptr));
2005 ASSERT_EQ(EINVAL, errno);
zijunzhao00a3dba2023-03-01 00:07:40 +00002006#pragma clang diagnostic pop
Elliott Hughes6b841db2014-08-20 16:10:49 -07002007#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002008 GTEST_SKIP() << "glibc is broken";
Elliott Hughes6b841db2014-08-20 16:10:49 -07002009#endif
2010}
Elliott Hughes31165ed2014-09-23 17:34:29 -07002011
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002012TEST(STDIO_TEST, fdopen_add_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07002013 // This fd doesn't have O_CLOEXEC...
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002014 int fd = open("/proc/version", O_RDONLY);
2015 ASSERT_FALSE(CloseOnExec(fd));
Elliott Hughes31165ed2014-09-23 17:34:29 -07002016 // ...but the new one does.
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002017 FILE* fp = fdopen(fd, "re");
2018 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2019 fclose(fp);
2020}
2021
2022TEST(STDIO_TEST, fdopen_remove_CLOEXEC) {
2023 // This fd has O_CLOEXEC...
2024 int fd = open("/proc/version", O_RDONLY | O_CLOEXEC);
2025 ASSERT_TRUE(CloseOnExec(fd));
2026 // ...but the new one doesn't.
2027 FILE* fp = fdopen(fd, "r");
2028 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2029 fclose(fp);
2030}
2031
2032TEST(STDIO_TEST, freopen_add_CLOEXEC) {
2033 // This FILE* doesn't have O_CLOEXEC...
2034 FILE* fp = fopen("/proc/version", "r");
2035 ASSERT_FALSE(CloseOnExec(fileno(fp)));
2036 // ...but the new one does.
2037 fp = freopen("/proc/version", "re", fp);
2038 ASSERT_TRUE(CloseOnExec(fileno(fp)));
Elliott Hughes31165ed2014-09-23 17:34:29 -07002039
2040 fclose(fp);
Elliott Hughes31165ed2014-09-23 17:34:29 -07002041}
2042
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002043TEST(STDIO_TEST, freopen_remove_CLOEXEC) {
2044 // This FILE* has O_CLOEXEC...
2045 FILE* fp = fopen("/proc/version", "re");
2046 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2047 // ...but the new one doesn't.
2048 fp = freopen("/proc/version", "r", fp);
2049 ASSERT_FALSE(CloseOnExec(fileno(fp)));
2050 fclose(fp);
2051}
Elliott Hughes31165ed2014-09-23 17:34:29 -07002052
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002053TEST(STDIO_TEST, freopen_null_filename_add_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07002054 // This FILE* doesn't have O_CLOEXEC...
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002055 FILE* fp = fopen("/proc/version", "r");
2056 ASSERT_FALSE(CloseOnExec(fileno(fp)));
Elliott Hughes31165ed2014-09-23 17:34:29 -07002057 // ...but the new one does.
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002058 fp = freopen(nullptr, "re", fp);
2059 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2060 fclose(fp);
2061}
Elliott Hughes31165ed2014-09-23 17:34:29 -07002062
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002063TEST(STDIO_TEST, freopen_null_filename_remove_CLOEXEC) {
2064 // This FILE* has O_CLOEXEC...
2065 FILE* fp = fopen("/proc/version", "re");
2066 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2067 // ...but the new one doesn't.
2068 fp = freopen(nullptr, "r", fp);
2069 ASSERT_FALSE(CloseOnExec(fileno(fp)));
Elliott Hughes31165ed2014-09-23 17:34:29 -07002070 fclose(fp);
2071}
Elliott Hughes20841a12014-12-01 16:13:30 -08002072
Elliott Hughesf226ee52016-02-03 11:24:28 -08002073TEST(STDIO_TEST, fopen64_freopen64) {
2074 FILE* fp = fopen64("/proc/version", "r");
2075 ASSERT_TRUE(fp != nullptr);
2076 fp = freopen64("/proc/version", "re", fp);
2077 ASSERT_TRUE(fp != nullptr);
2078 fclose(fp);
2079}
2080
Elliott Hughes20841a12014-12-01 16:13:30 -08002081// https://code.google.com/p/android/issues/detail?id=81155
2082// http://b/18556607
Christopher Ferris13f26a72016-01-13 13:47:58 -08002083TEST(STDIO_TEST, fread_unbuffered_pathological_performance) {
Elliott Hughes20841a12014-12-01 16:13:30 -08002084 FILE* fp = fopen("/dev/zero", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07002085 ASSERT_TRUE(fp != nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08002086
2087 // Make this stream unbuffered.
Yi Kong32bc0fc2018-08-02 17:31:13 -07002088 setvbuf(fp, nullptr, _IONBF, 0);
Elliott Hughes20841a12014-12-01 16:13:30 -08002089
2090 char buf[65*1024];
2091 memset(buf, 0xff, sizeof(buf));
2092
Yi Kong32bc0fc2018-08-02 17:31:13 -07002093 time_t t0 = time(nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08002094 for (size_t i = 0; i < 1024; ++i) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002095 ASSERT_EQ(1U, fread(buf, 64*1024, 1, fp));
Elliott Hughes20841a12014-12-01 16:13:30 -08002096 }
Yi Kong32bc0fc2018-08-02 17:31:13 -07002097 time_t t1 = time(nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08002098
2099 fclose(fp);
2100
2101 // 1024 64KiB reads should have been very quick.
2102 ASSERT_LE(t1 - t0, 1);
2103
2104 for (size_t i = 0; i < 64*1024; ++i) {
2105 ASSERT_EQ('\0', buf[i]);
2106 }
2107 for (size_t i = 64*1024; i < 65*1024; ++i) {
2108 ASSERT_EQ('\xff', buf[i]);
2109 }
2110}
Elliott Hughes75b99382015-01-20 11:23:50 -08002111
Christopher Ferris13f26a72016-01-13 13:47:58 -08002112TEST(STDIO_TEST, fread_EOF) {
Elliott Hughes0ed7e082015-01-22 15:13:38 -08002113 std::string digits("0123456789");
2114 FILE* fp = fmemopen(&digits[0], digits.size(), "r");
Elliott Hughes75b99382015-01-20 11:23:50 -08002115
2116 // Try to read too much, but little enough that it still fits in the FILE's internal buffer.
2117 char buf1[4 * 4];
2118 memset(buf1, 0, sizeof(buf1));
2119 ASSERT_EQ(2U, fread(buf1, 4, 4, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08002120 ASSERT_STREQ("0123456789", buf1);
Elliott Hughes75b99382015-01-20 11:23:50 -08002121 ASSERT_TRUE(feof(fp));
2122
2123 rewind(fp);
2124
Elliott Hughes0ed7e082015-01-22 15:13:38 -08002125 // Try to read way too much so stdio tries to read more direct from the stream.
2126 char buf2[4 * 4096];
Elliott Hughes75b99382015-01-20 11:23:50 -08002127 memset(buf2, 0, sizeof(buf2));
2128 ASSERT_EQ(2U, fread(buf2, 4, 4096, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08002129 ASSERT_STREQ("0123456789", buf2);
Elliott Hughes75b99382015-01-20 11:23:50 -08002130 ASSERT_TRUE(feof(fp));
2131
2132 fclose(fp);
2133}
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002134
2135static void test_fread_from_write_only_stream(size_t n) {
2136 FILE* fp = fopen("/dev/null", "w");
2137 std::vector<char> buf(n, 0);
2138 errno = 0;
2139 ASSERT_EQ(0U, fread(&buf[0], n, 1, fp));
2140 ASSERT_EQ(EBADF, errno);
2141 ASSERT_TRUE(ferror(fp));
2142 ASSERT_FALSE(feof(fp));
2143 fclose(fp);
2144}
2145
Christopher Ferris13f26a72016-01-13 13:47:58 -08002146TEST(STDIO_TEST, fread_from_write_only_stream_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002147 test_fread_from_write_only_stream(1);
2148}
2149
Christopher Ferris13f26a72016-01-13 13:47:58 -08002150TEST(STDIO_TEST, fread_from_write_only_stream_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002151 test_fread_from_write_only_stream(64*1024);
2152}
2153
2154static void test_fwrite_after_fread(size_t n) {
2155 TemporaryFile tf;
2156
2157 FILE* fp = fdopen(tf.fd, "w+");
2158 ASSERT_EQ(1U, fwrite("1", 1, 1, fp));
2159 fflush(fp);
2160
2161 // We've flushed but not rewound, so there's nothing to read.
2162 std::vector<char> buf(n, 0);
2163 ASSERT_EQ(0U, fread(&buf[0], 1, buf.size(), fp));
2164 ASSERT_TRUE(feof(fp));
2165
2166 // But hitting EOF doesn't prevent us from writing...
2167 errno = 0;
Elliott Hughes9677fab2016-01-25 15:50:59 -08002168 ASSERT_EQ(1U, fwrite("2", 1, 1, fp)) << strerror(errno);
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002169
2170 // And if we rewind, everything's there.
2171 rewind(fp);
2172 ASSERT_EQ(2U, fread(&buf[0], 1, buf.size(), fp));
2173 ASSERT_EQ('1', buf[0]);
2174 ASSERT_EQ('2', buf[1]);
2175
2176 fclose(fp);
2177}
2178
Christopher Ferris13f26a72016-01-13 13:47:58 -08002179TEST(STDIO_TEST, fwrite_after_fread_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002180 test_fwrite_after_fread(16);
2181}
2182
Christopher Ferris13f26a72016-01-13 13:47:58 -08002183TEST(STDIO_TEST, fwrite_after_fread_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002184 test_fwrite_after_fread(64*1024);
2185}
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002186
2187// http://b/19172514
Christopher Ferris13f26a72016-01-13 13:47:58 -08002188TEST(STDIO_TEST, fread_after_fseek) {
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002189 TemporaryFile tf;
2190
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002191 FILE* fp = fopen(tf.path, "w+");
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002192 ASSERT_TRUE(fp != nullptr);
2193
2194 char file_data[12288];
2195 for (size_t i = 0; i < 12288; i++) {
2196 file_data[i] = i;
2197 }
2198 ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp));
2199 fclose(fp);
2200
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002201 fp = fopen(tf.path, "r");
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002202 ASSERT_TRUE(fp != nullptr);
2203
2204 char buffer[8192];
2205 size_t cur_location = 0;
2206 // Small read to populate internal buffer.
2207 ASSERT_EQ(100U, fread(buffer, 1, 100, fp));
2208 ASSERT_EQ(memcmp(file_data, buffer, 100), 0);
2209
2210 cur_location = static_cast<size_t>(ftell(fp));
2211 // Large read to force reading into the user supplied buffer and bypassing
2212 // the internal buffer.
2213 ASSERT_EQ(8192U, fread(buffer, 1, 8192, fp));
2214 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 8192), 0);
2215
2216 // Small backwards seek to verify fseek does not reuse the internal buffer.
Elliott Hughes9677fab2016-01-25 15:50:59 -08002217 ASSERT_EQ(0, fseek(fp, -22, SEEK_CUR)) << strerror(errno);
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002218 cur_location = static_cast<size_t>(ftell(fp));
2219 ASSERT_EQ(22U, fread(buffer, 1, 22, fp));
2220 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 22), 0);
2221
2222 fclose(fp);
2223}
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002224
2225// https://code.google.com/p/android/issues/detail?id=184847
Christopher Ferris13f26a72016-01-13 13:47:58 -08002226TEST(STDIO_TEST, fread_EOF_184847) {
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002227 TemporaryFile tf;
2228 char buf[6] = {0};
2229
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002230 FILE* fw = fopen(tf.path, "w");
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002231 ASSERT_TRUE(fw != nullptr);
2232
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002233 FILE* fr = fopen(tf.path, "r");
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002234 ASSERT_TRUE(fr != nullptr);
2235
2236 fwrite("a", 1, 1, fw);
2237 fflush(fw);
2238 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
2239 ASSERT_STREQ("a", buf);
2240
2241 // 'fr' is now at EOF.
2242 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
2243 ASSERT_TRUE(feof(fr));
2244
2245 // Write some more...
2246 fwrite("z", 1, 1, fw);
2247 fflush(fw);
2248
2249 // ...and check that we can read it back.
2250 // (BSD thinks that once a stream has hit EOF, it must always return EOF. SysV disagrees.)
2251 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
2252 ASSERT_STREQ("z", buf);
2253
2254 // But now we're done.
2255 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
2256
2257 fclose(fr);
2258 fclose(fw);
2259}
Elliott Hughes923f1652016-01-19 15:46:05 -08002260
2261TEST(STDIO_TEST, fclose_invalidates_fd) {
2262 // The typical error we're trying to help people catch involves accessing
2263 // memory after it's been freed. But we know that stdin/stdout/stderr are
2264 // special and don't get deallocated, so this test uses stdin.
2265 ASSERT_EQ(0, fclose(stdin));
2266
2267 // Even though using a FILE* after close is undefined behavior, I've closed
2268 // this bug as "WAI" too many times. We shouldn't hand out stale fds,
2269 // especially because they might actually correspond to a real stream.
2270 errno = 0;
2271 ASSERT_EQ(-1, fileno(stdin));
2272 ASSERT_EQ(EBADF, errno);
2273}
Elliott Hughes2704bd12016-01-20 17:14:53 -08002274
2275TEST(STDIO_TEST, fseek_ftell_unseekable) {
2276#if defined(__BIONIC__) // glibc has fopencookie instead.
2277 auto read_fn = [](void*, char*, int) { return -1; };
2278 FILE* fp = funopen(nullptr, read_fn, nullptr, nullptr, nullptr);
2279 ASSERT_TRUE(fp != nullptr);
2280
2281 // Check that ftell balks on an unseekable FILE*.
2282 errno = 0;
2283 ASSERT_EQ(-1, ftell(fp));
2284 ASSERT_EQ(ESPIPE, errno);
2285
2286 // SEEK_CUR is rewritten as SEEK_SET internally...
2287 errno = 0;
2288 ASSERT_EQ(-1, fseek(fp, 0, SEEK_CUR));
2289 ASSERT_EQ(ESPIPE, errno);
2290
2291 // ...so it's worth testing the direct seek path too.
2292 errno = 0;
2293 ASSERT_EQ(-1, fseek(fp, 0, SEEK_SET));
2294 ASSERT_EQ(ESPIPE, errno);
2295
2296 fclose(fp);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002297#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002298 GTEST_SKIP() << "glibc uses fopencookie instead";
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002299#endif
2300}
2301
2302TEST(STDIO_TEST, funopen_EINVAL) {
2303#if defined(__BIONIC__)
2304 errno = 0;
2305 ASSERT_EQ(nullptr, funopen(nullptr, nullptr, nullptr, nullptr, nullptr));
2306 ASSERT_EQ(EINVAL, errno);
2307#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002308 GTEST_SKIP() << "glibc uses fopencookie instead";
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002309#endif
2310}
2311
2312TEST(STDIO_TEST, funopen_seek) {
2313#if defined(__BIONIC__)
2314 auto read_fn = [](void*, char*, int) { return -1; };
2315
2316 auto seek_fn = [](void*, fpos_t, int) -> fpos_t { return 0xfedcba12; };
2317 auto seek64_fn = [](void*, fpos64_t, int) -> fpos64_t { return 0xfedcba12345678; };
2318
2319 FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr);
2320 ASSERT_TRUE(fp != nullptr);
2321 fpos_t pos;
Elliott Hughes955426e2016-01-26 18:25:52 -08002322#if defined(__LP64__)
2323 EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno);
2324 EXPECT_EQ(0xfedcba12LL, pos);
2325#else
2326 EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno);
2327 EXPECT_EQ(EOVERFLOW, errno);
2328#endif
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002329
2330 FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr);
2331 ASSERT_TRUE(fp64 != nullptr);
2332 fpos64_t pos64;
Elliott Hughes955426e2016-01-26 18:25:52 -08002333 EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno);
2334 EXPECT_EQ(0xfedcba12345678, pos64);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002335#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002336 GTEST_SKIP() << "glibc uses fopencookie instead";
Elliott Hughes2704bd12016-01-20 17:14:53 -08002337#endif
2338}
Elliott Hughes71288cb2016-01-22 19:22:44 -08002339
2340TEST(STDIO_TEST, lots_of_concurrent_files) {
2341 std::vector<TemporaryFile*> tfs;
2342 std::vector<FILE*> fps;
2343
2344 for (size_t i = 0; i < 256; ++i) {
2345 TemporaryFile* tf = new TemporaryFile;
2346 tfs.push_back(tf);
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002347 FILE* fp = fopen(tf->path, "w+");
Elliott Hughes71288cb2016-01-22 19:22:44 -08002348 fps.push_back(fp);
2349 fprintf(fp, "hello %zu!\n", i);
2350 fflush(fp);
2351 }
2352
2353 for (size_t i = 0; i < 256; ++i) {
Elliott Hughes71288cb2016-01-22 19:22:44 -08002354 char expected[BUFSIZ];
2355 snprintf(expected, sizeof(expected), "hello %zu!\n", i);
Elliott Hughes71288cb2016-01-22 19:22:44 -08002356
Elliott Hughes70715da2016-08-01 16:35:17 -07002357 AssertFileIs(fps[i], expected);
Elliott Hughes71288cb2016-01-22 19:22:44 -08002358 fclose(fps[i]);
2359 delete tfs[i];
2360 }
2361}
Elliott Hughes9677fab2016-01-25 15:50:59 -08002362
2363static void AssertFileOffsetAt(FILE* fp, off64_t offset) {
2364 EXPECT_EQ(offset, ftell(fp));
2365 EXPECT_EQ(offset, ftello(fp));
Elliott Hughese4fa6e92016-02-02 22:39:15 -08002366 EXPECT_EQ(offset, ftello64(fp));
Elliott Hughes9677fab2016-01-25 15:50:59 -08002367 fpos_t pos;
2368 fpos64_t pos64;
2369 EXPECT_EQ(0, fgetpos(fp, &pos));
2370 EXPECT_EQ(0, fgetpos64(fp, &pos64));
2371#if defined(__BIONIC__)
2372 EXPECT_EQ(offset, static_cast<off64_t>(pos));
2373 EXPECT_EQ(offset, static_cast<off64_t>(pos64));
2374#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002375 GTEST_SKIP() << "glibc's fpos_t is opaque";
Elliott Hughes9677fab2016-01-25 15:50:59 -08002376#endif
2377}
2378
2379TEST(STDIO_TEST, seek_tell_family_smoke) {
2380 TemporaryFile tf;
2381 FILE* fp = fdopen(tf.fd, "w+");
2382
2383 // Initially we should be at 0.
2384 AssertFileOffsetAt(fp, 0);
2385
2386 // Seek to offset 8192.
2387 ASSERT_EQ(0, fseek(fp, 8192, SEEK_SET));
2388 AssertFileOffsetAt(fp, 8192);
2389 fpos_t eight_k_pos;
2390 ASSERT_EQ(0, fgetpos(fp, &eight_k_pos));
2391
2392 // Seek forward another 8192...
2393 ASSERT_EQ(0, fseek(fp, 8192, SEEK_CUR));
2394 AssertFileOffsetAt(fp, 8192 + 8192);
2395 fpos64_t sixteen_k_pos64;
2396 ASSERT_EQ(0, fgetpos64(fp, &sixteen_k_pos64));
2397
2398 // Seek back 8192...
2399 ASSERT_EQ(0, fseek(fp, -8192, SEEK_CUR));
2400 AssertFileOffsetAt(fp, 8192);
2401
2402 // Since we haven't written anything, the end is also at 0.
2403 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2404 AssertFileOffsetAt(fp, 0);
2405
2406 // Check that our fpos64_t from 16KiB works...
2407 ASSERT_EQ(0, fsetpos64(fp, &sixteen_k_pos64));
2408 AssertFileOffsetAt(fp, 8192 + 8192);
2409 // ...as does our fpos_t from 8192.
2410 ASSERT_EQ(0, fsetpos(fp, &eight_k_pos));
2411 AssertFileOffsetAt(fp, 8192);
2412
2413 // Do fseeko and fseeko64 work too?
2414 ASSERT_EQ(0, fseeko(fp, 1234, SEEK_SET));
2415 AssertFileOffsetAt(fp, 1234);
2416 ASSERT_EQ(0, fseeko64(fp, 5678, SEEK_SET));
2417 AssertFileOffsetAt(fp, 5678);
2418
2419 fclose(fp);
2420}
2421
2422TEST(STDIO_TEST, fseek_fseeko_EINVAL) {
2423 TemporaryFile tf;
2424 FILE* fp = fdopen(tf.fd, "w+");
2425
2426 // Bad whence.
2427 errno = 0;
2428 ASSERT_EQ(-1, fseek(fp, 0, 123));
2429 ASSERT_EQ(EINVAL, errno);
2430 errno = 0;
2431 ASSERT_EQ(-1, fseeko(fp, 0, 123));
2432 ASSERT_EQ(EINVAL, errno);
2433 errno = 0;
2434 ASSERT_EQ(-1, fseeko64(fp, 0, 123));
2435 ASSERT_EQ(EINVAL, errno);
2436
2437 // Bad offset.
2438 errno = 0;
2439 ASSERT_EQ(-1, fseek(fp, -1, SEEK_SET));
2440 ASSERT_EQ(EINVAL, errno);
2441 errno = 0;
2442 ASSERT_EQ(-1, fseeko(fp, -1, SEEK_SET));
2443 ASSERT_EQ(EINVAL, errno);
2444 errno = 0;
2445 ASSERT_EQ(-1, fseeko64(fp, -1, SEEK_SET));
2446 ASSERT_EQ(EINVAL, errno);
2447
2448 fclose(fp);
2449}
Elliott Hughes20788ae2016-06-09 15:16:32 -07002450
2451TEST(STDIO_TEST, ctermid) {
2452 ASSERT_STREQ("/dev/tty", ctermid(nullptr));
2453
2454 char buf[L_ctermid] = {};
2455 ASSERT_EQ(buf, ctermid(buf));
2456 ASSERT_STREQ("/dev/tty", buf);
2457}
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002458
2459TEST(STDIO_TEST, remove) {
2460 struct stat sb;
2461
2462 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002463 ASSERT_EQ(0, remove(tf.path));
2464 ASSERT_EQ(-1, lstat(tf.path, &sb));
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002465 ASSERT_EQ(ENOENT, errno);
2466
2467 TemporaryDir td;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002468 ASSERT_EQ(0, remove(td.path));
2469 ASSERT_EQ(-1, lstat(td.path, &sb));
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002470 ASSERT_EQ(ENOENT, errno);
2471
2472 errno = 0;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002473 ASSERT_EQ(-1, remove(tf.path));
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002474 ASSERT_EQ(ENOENT, errno);
2475
2476 errno = 0;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002477 ASSERT_EQ(-1, remove(td.path));
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002478 ASSERT_EQ(ENOENT, errno);
2479}
Elliott Hughesfb3873d2016-08-10 11:07:54 -07002480
Elliott Hughese657eb42021-02-18 17:11:56 -08002481TEST_F(STDIO_DEATHTEST, snprintf_30445072_known_buffer_size) {
Elliott Hughesfb3873d2016-08-10 11:07:54 -07002482 char buf[16];
2483 ASSERT_EXIT(snprintf(buf, atol("-1"), "hello"),
2484 testing::KilledBySignal(SIGABRT),
2485#if defined(NOFORTIFY)
2486 "FORTIFY: vsnprintf: size .* > SSIZE_MAX"
2487#else
2488 "FORTIFY: vsnprintf: prevented .*-byte write into 16-byte buffer"
2489#endif
2490 );
2491}
2492
Elliott Hughese657eb42021-02-18 17:11:56 -08002493TEST_F(STDIO_DEATHTEST, snprintf_30445072_unknown_buffer_size) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002494 std::string buf = "hello"; // So the compiler doesn't know the buffer size.
Elliott Hughesfb3873d2016-08-10 11:07:54 -07002495 ASSERT_EXIT(snprintf(&buf[0], atol("-1"), "hello"),
2496 testing::KilledBySignal(SIGABRT),
2497 "FORTIFY: vsnprintf: size .* > SSIZE_MAX");
2498}
2499
2500TEST(STDIO_TEST, sprintf_30445072) {
2501 std::string buf = "world";
2502 sprintf(&buf[0], "hello");
2503 ASSERT_EQ(buf, "hello");
2504}
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002505
Elliott Hughes654cd832018-08-30 16:00:42 -07002506TEST(STDIO_TEST, printf_m) {
Elliott Hughes654cd832018-08-30 16:00:42 -07002507 errno = 0;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002508 EXPECT_SNPRINTF("<Success>", "<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002509 errno = -1;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002510 EXPECT_SNPRINTF("<Unknown error -1>", "<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002511 errno = EINVAL;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002512 EXPECT_SNPRINTF("<Invalid argument>", "<%m>");
Elliott Hughesf340a562018-09-06 10:42:40 -07002513}
2514
Elliott Hughes654cd832018-08-30 16:00:42 -07002515TEST(STDIO_TEST, wprintf_m) {
Elliott Hughes654cd832018-08-30 16:00:42 -07002516 errno = 0;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002517 EXPECT_SWPRINTF(L"<Success>", L"<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002518 errno = -1;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002519 EXPECT_SWPRINTF(L"<Unknown error -1>", L"<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002520 errno = EINVAL;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002521 EXPECT_SWPRINTF(L"<Invalid argument>", L"<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002522}
2523
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002524TEST(STDIO_TEST, printf_m_does_not_clobber_strerror) {
Elliott Hughesf340a562018-09-06 10:42:40 -07002525 const char* m = strerror(-1);
2526 ASSERT_STREQ("Unknown error -1", m);
2527 errno = -2;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002528 EXPECT_SNPRINTF("<Unknown error -2>", "<%m>");
2529 ASSERT_STREQ("Unknown error -1", m);
2530}
2531
2532TEST(STDIO_TEST, wprintf_m_does_not_clobber_strerror) {
2533 const char* m = strerror(-1);
2534 ASSERT_STREQ("Unknown error -1", m);
2535 errno = -2;
2536 EXPECT_SWPRINTF(L"<Unknown error -2>", L"<%m>");
Elliott Hughesf340a562018-09-06 10:42:40 -07002537 ASSERT_STREQ("Unknown error -1", m);
2538}
2539
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002540TEST(STDIO_TEST, fopen_append_mode_and_ftell) {
2541 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002542 SetFileTo(tf.path, "0123456789");
2543 FILE* fp = fopen(tf.path, "a");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002544 EXPECT_EQ(10, ftell(fp));
2545 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2546 EXPECT_EQ(2, ftell(fp));
2547 ASSERT_NE(EOF, fputs("xxx", fp));
2548 ASSERT_EQ(0, fflush(fp));
2549 EXPECT_EQ(13, ftell(fp));
2550 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2551 EXPECT_EQ(13, ftell(fp));
2552 ASSERT_EQ(0, fclose(fp));
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002553 AssertFileIs(tf.path, "0123456789xxx");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002554}
2555
2556TEST(STDIO_TEST, fdopen_append_mode_and_ftell) {
2557 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002558 SetFileTo(tf.path, "0123456789");
2559 int fd = open(tf.path, O_RDWR);
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002560 ASSERT_NE(-1, fd);
2561 // POSIX: "The file position indicator associated with the new stream is set to the position
2562 // indicated by the file offset associated with the file descriptor."
2563 ASSERT_EQ(4, lseek(fd, 4, SEEK_SET));
2564 FILE* fp = fdopen(fd, "a");
2565 EXPECT_EQ(4, ftell(fp));
2566 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2567 EXPECT_EQ(2, ftell(fp));
2568 ASSERT_NE(EOF, fputs("xxx", fp));
2569 ASSERT_EQ(0, fflush(fp));
2570 EXPECT_EQ(13, ftell(fp));
2571 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2572 EXPECT_EQ(13, ftell(fp));
2573 ASSERT_EQ(0, fclose(fp));
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002574 AssertFileIs(tf.path, "0123456789xxx");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002575}
2576
2577TEST(STDIO_TEST, freopen_append_mode_and_ftell) {
2578 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002579 SetFileTo(tf.path, "0123456789");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002580 FILE* other_fp = fopen("/proc/version", "r");
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002581 FILE* fp = freopen(tf.path, "a", other_fp);
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002582 EXPECT_EQ(10, ftell(fp));
2583 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2584 EXPECT_EQ(2, ftell(fp));
2585 ASSERT_NE(EOF, fputs("xxx", fp));
2586 ASSERT_EQ(0, fflush(fp));
2587 EXPECT_EQ(13, ftell(fp));
2588 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2589 EXPECT_EQ(13, ftell(fp));
2590 ASSERT_EQ(0, fclose(fp));
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002591 AssertFileIs(tf.path, "0123456789xxx");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002592}
Elliott Hughesb15feb72017-07-31 17:20:18 -07002593
2594TEST(STDIO_TEST, constants) {
2595 ASSERT_LE(FILENAME_MAX, PATH_MAX);
2596 ASSERT_EQ(L_tmpnam, PATH_MAX);
2597}
Elliott Hughes37ad9592017-10-30 17:47:12 -07002598
2599TEST(STDIO_TEST, perror) {
2600 ExecTestHelper eth;
Steven Moreland4ef83d62021-10-07 00:19:18 +00002601 eth.Run([&]() { errno = EINVAL; perror("a b c"); exit(0); }, 0, "a b c: Invalid argument\n");
2602 eth.Run([&]() { errno = EINVAL; perror(nullptr); exit(0); }, 0, "Invalid argument\n");
2603 eth.Run([&]() { errno = EINVAL; perror(""); exit(0); }, 0, "Invalid argument\n");
Elliott Hughes37ad9592017-10-30 17:47:12 -07002604}
2605
2606TEST(STDIO_TEST, puts) {
2607 ExecTestHelper eth;
2608 eth.Run([&]() { exit(puts("a b c")); }, 0, "a b c\n");
2609}
2610
Elliott Hughes7cebf832020-08-12 14:25:41 -07002611TEST(STDIO_TEST, putchar) {
2612 ExecTestHelper eth;
2613 eth.Run([&]() { exit(putchar('A')); }, 65, "A");
2614}
2615
2616TEST(STDIO_TEST, putchar_unlocked) {
2617 ExecTestHelper eth;
2618 eth.Run([&]() { exit(putchar('B')); }, 66, "B");
2619}
2620
Elliott Hughes37ad9592017-10-30 17:47:12 -07002621TEST(STDIO_TEST, unlocked) {
2622 TemporaryFile tf;
2623
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002624 FILE* fp = fopen(tf.path, "w+");
Elliott Hughes37ad9592017-10-30 17:47:12 -07002625 ASSERT_TRUE(fp != nullptr);
2626
2627 clearerr_unlocked(fp);
2628 ASSERT_FALSE(feof_unlocked(fp));
2629 ASSERT_FALSE(ferror_unlocked(fp));
2630
2631 ASSERT_EQ(fileno(fp), fileno_unlocked(fp));
2632
2633 ASSERT_NE(EOF, putc_unlocked('a', fp));
2634 ASSERT_NE(EOF, putc('b', fp));
2635 ASSERT_NE(EOF, fputc_unlocked('c', fp));
2636 ASSERT_NE(EOF, fputc('d', fp));
2637
2638 rewind(fp);
2639 ASSERT_EQ('a', getc_unlocked(fp));
2640 ASSERT_EQ('b', getc(fp));
2641 ASSERT_EQ('c', fgetc_unlocked(fp));
2642 ASSERT_EQ('d', fgetc(fp));
2643
2644 rewind(fp);
2645 ASSERT_EQ(2U, fwrite_unlocked("AB", 1, 2, fp));
2646 ASSERT_EQ(2U, fwrite("CD", 1, 2, fp));
2647 ASSERT_EQ(0, fflush_unlocked(fp));
2648
2649 rewind(fp);
2650 char buf[BUFSIZ] = {};
2651 ASSERT_EQ(2U, fread_unlocked(&buf[0], 1, 2, fp));
2652 ASSERT_EQ(2U, fread(&buf[2], 1, 2, fp));
2653 ASSERT_STREQ("ABCD", buf);
2654
2655 rewind(fp);
2656 ASSERT_NE(EOF, fputs("hello ", fp));
2657 ASSERT_NE(EOF, fputs_unlocked("world", fp));
2658 ASSERT_NE(EOF, fputc('\n', fp));
2659
2660 rewind(fp);
2661 ASSERT_TRUE(fgets_unlocked(buf, sizeof(buf), fp) != nullptr);
2662 ASSERT_STREQ("hello world\n", buf);
2663
2664 ASSERT_EQ(0, fclose(fp));
2665}
Ryan Prichardbf549862017-11-07 15:30:32 -08002666
2667TEST(STDIO_TEST, fseek_64bit) {
2668 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002669 FILE* fp = fopen64(tf.path, "w+");
Ryan Prichardbf549862017-11-07 15:30:32 -08002670 ASSERT_TRUE(fp != nullptr);
2671 ASSERT_EQ(0, fseeko64(fp, 0x2'0000'0000, SEEK_SET));
2672 ASSERT_EQ(0x2'0000'0000, ftello64(fp));
2673 ASSERT_EQ(0, fseeko64(fp, 0x1'0000'0000, SEEK_CUR));
2674 ASSERT_EQ(0x3'0000'0000, ftello64(fp));
2675 ASSERT_EQ(0, fclose(fp));
2676}
2677
2678// POSIX requires that fseek/fseeko fail with EOVERFLOW if the new file offset
2679// isn't representable in long/off_t.
2680TEST(STDIO_TEST, fseek_overflow_32bit) {
2681 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002682 FILE* fp = fopen64(tf.path, "w+");
Ryan Prichardbf549862017-11-07 15:30:32 -08002683 ASSERT_EQ(0, ftruncate64(fileno(fp), 0x2'0000'0000));
2684
2685 // Bionic implements overflow checking for SEEK_CUR, but glibc doesn't.
2686#if defined(__BIONIC__) && !defined(__LP64__)
2687 ASSERT_EQ(0, fseek(fp, 0x7fff'ffff, SEEK_SET));
2688 ASSERT_EQ(-1, fseek(fp, 1, SEEK_CUR));
2689 ASSERT_EQ(EOVERFLOW, errno);
2690#endif
2691
2692 // Neither Bionic nor glibc implement the overflow checking for SEEK_END.
2693 // (Aside: FreeBSD's libc is an example of a libc that checks both SEEK_CUR
2694 // and SEEK_END -- many C libraries check neither.)
2695 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2696 ASSERT_EQ(0x2'0000'0000, ftello64(fp));
2697
2698 fclose(fp);
2699}
Elliott Hughesf1a38382018-08-22 15:38:07 -07002700
2701TEST(STDIO_TEST, dev_std_files) {
2702 // POSIX only mentions /dev/stdout, but we should have all three (http://b/31824379).
2703 char path[PATH_MAX];
Christopher Ferris2c4ec7e2018-08-23 11:17:55 -07002704 ssize_t length = readlink("/dev/stdin", path, sizeof(path));
2705 ASSERT_LT(0, length);
2706 ASSERT_EQ("/proc/self/fd/0", std::string(path, length));
2707
2708 length = readlink("/dev/stdout", path, sizeof(path));
2709 ASSERT_LT(0, length);
2710 ASSERT_EQ("/proc/self/fd/1", std::string(path, length));
2711
2712 length = readlink("/dev/stderr", path, sizeof(path));
2713 ASSERT_LT(0, length);
2714 ASSERT_EQ("/proc/self/fd/2", std::string(path, length));
Elliott Hughesf1a38382018-08-22 15:38:07 -07002715}
Ryan Prichardc485cdb2019-04-30 14:47:34 -07002716
2717TEST(STDIO_TEST, fread_with_locked_file) {
2718 // Reading an unbuffered/line-buffered file from one thread shouldn't block on
2719 // files locked on other threads, even if it flushes some line-buffered files.
2720 FILE* fp1 = fopen("/dev/zero", "r");
2721 ASSERT_TRUE(fp1 != nullptr);
2722 flockfile(fp1);
2723
2724 std::thread([] {
2725 for (int mode : { _IONBF, _IOLBF }) {
2726 FILE* fp2 = fopen("/dev/zero", "r");
2727 ASSERT_TRUE(fp2 != nullptr);
2728 setvbuf(fp2, nullptr, mode, 0);
2729 ASSERT_EQ('\0', fgetc(fp2));
2730 fclose(fp2);
2731 }
2732 }).join();
2733
2734 funlockfile(fp1);
2735 fclose(fp1);
2736}
Elliott Hughes31c73092019-05-07 10:03:02 -07002737
2738TEST(STDIO_TEST, SEEK_macros) {
2739 ASSERT_EQ(0, SEEK_SET);
2740 ASSERT_EQ(1, SEEK_CUR);
2741 ASSERT_EQ(2, SEEK_END);
2742 ASSERT_EQ(3, SEEK_DATA);
2743 ASSERT_EQ(4, SEEK_HOLE);
2744 // So we'll notice if Linux grows another constant in <linux/fs.h>...
2745 ASSERT_EQ(SEEK_MAX, SEEK_HOLE);
2746}
Elliott Hughes05b675e2019-04-17 13:01:06 -07002747
2748TEST(STDIO_TEST, rename) {
2749 TemporaryDir td;
2750 std::string old_path = td.path + "/old"s;
2751 std::string new_path = td.path + "/new"s;
2752
2753 // Create the file, check it exists.
2754 ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
2755 struct stat sb;
2756 ASSERT_EQ(0, stat(old_path.c_str(), &sb));
2757 ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
2758
2759 // Rename and check it moved.
2760 ASSERT_EQ(0, rename(old_path.c_str(), new_path.c_str()));
2761 ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
2762 ASSERT_EQ(0, stat(new_path.c_str(), &sb));
2763}
2764
2765TEST(STDIO_TEST, renameat) {
2766 TemporaryDir td;
2767 android::base::unique_fd dirfd{open(td.path, O_PATH)};
2768 std::string old_path = td.path + "/old"s;
2769 std::string new_path = td.path + "/new"s;
2770
2771 // Create the file, check it exists.
2772 ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
2773 struct stat sb;
2774 ASSERT_EQ(0, stat(old_path.c_str(), &sb));
2775 ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
2776
2777 // Rename and check it moved.
2778 ASSERT_EQ(0, renameat(dirfd, "old", dirfd, "new"));
2779 ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
2780 ASSERT_EQ(0, stat(new_path.c_str(), &sb));
2781}
2782
2783TEST(STDIO_TEST, renameat2) {
Colin Cross4c5595c2021-08-16 15:51:59 -07002784#if defined(__GLIBC__) || defined(ANDROID_HOST_MUSL)
Colin Cross7da20342021-07-28 11:18:11 -07002785 GTEST_SKIP() << "glibc doesn't have renameat2 until 2.28 and musl doesn't have renameat2";
Elliott Hughes05b675e2019-04-17 13:01:06 -07002786#else
2787 TemporaryDir td;
2788 android::base::unique_fd dirfd{open(td.path, O_PATH)};
2789 std::string old_path = td.path + "/old"s;
2790 std::string new_path = td.path + "/new"s;
2791
2792 // Create the file, check it exists.
2793 ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
2794 struct stat sb;
2795 ASSERT_EQ(0, stat(old_path.c_str(), &sb));
2796 ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
2797
2798 // Rename and check it moved.
2799 ASSERT_EQ(0, renameat2(dirfd, "old", dirfd, "new", 0));
2800 ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
2801 ASSERT_EQ(0, stat(new_path.c_str(), &sb));
2802
2803 // After this, both "old" and "new" exist.
2804 ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
2805
2806 // Rename and check it moved.
2807 ASSERT_EQ(-1, renameat2(dirfd, "old", dirfd, "new", RENAME_NOREPLACE));
2808 ASSERT_EQ(EEXIST, errno);
2809#endif
2810}
2811
2812TEST(STDIO_TEST, renameat2_flags) {
2813#if defined(__GLIBC__)
2814 GTEST_SKIP() << "glibc doesn't have renameat2 until 2.28";
2815#else
2816 ASSERT_NE(0, RENAME_EXCHANGE);
2817 ASSERT_NE(0, RENAME_NOREPLACE);
2818 ASSERT_NE(0, RENAME_WHITEOUT);
2819#endif
2820}
Elliott Hughes7cebf832020-08-12 14:25:41 -07002821
2822TEST(STDIO_TEST, fdopen_failures) {
2823 FILE* fp;
2824 int fd = open("/proc/version", O_RDONLY);
2825 ASSERT_TRUE(fd != -1);
2826
2827 // Nonsense mode.
2828 errno = 0;
2829 fp = fdopen(fd, "nonsense");
2830 ASSERT_TRUE(fp == nullptr);
2831 ASSERT_EQ(EINVAL, errno);
2832
2833 // Mode that isn't a subset of the fd's actual mode.
2834 errno = 0;
2835 fp = fdopen(fd, "w");
2836 ASSERT_TRUE(fp == nullptr);
2837 ASSERT_EQ(EINVAL, errno);
2838
2839 // Can't set append on the underlying fd.
2840 errno = 0;
2841 fp = fdopen(fd, "a");
2842 ASSERT_TRUE(fp == nullptr);
2843 ASSERT_EQ(EINVAL, errno);
2844
2845 // Bad fd.
2846 errno = 0;
2847 fp = fdopen(-1, "re");
2848 ASSERT_TRUE(fp == nullptr);
2849 ASSERT_EQ(EBADF, errno);
2850
2851 close(fd);
2852}
2853
2854TEST(STDIO_TEST, fmemopen_invalid_mode) {
2855 errno = 0;
2856 FILE* fp = fmemopen(nullptr, 16, "nonsense");
2857 ASSERT_TRUE(fp == nullptr);
2858 ASSERT_EQ(EINVAL, errno);
2859}
2860
2861TEST(STDIO_TEST, fopen_invalid_mode) {
2862 errno = 0;
2863 FILE* fp = fopen("/proc/version", "nonsense");
2864 ASSERT_TRUE(fp == nullptr);
2865 ASSERT_EQ(EINVAL, errno);
2866}
2867
2868TEST(STDIO_TEST, freopen_invalid_mode) {
2869 FILE* fp = fopen("/proc/version", "re");
2870 ASSERT_TRUE(fp != nullptr);
2871
2872 errno = 0;
2873 fp = freopen("/proc/version", "nonsense", fp);
2874 ASSERT_TRUE(fp == nullptr);
2875 ASSERT_EQ(EINVAL, errno);
2876}
2877
2878TEST(STDIO_TEST, asprintf_smoke) {
2879 char* p = nullptr;
2880 ASSERT_EQ(11, asprintf(&p, "hello %s", "world"));
2881 ASSERT_STREQ("hello world", p);
2882 free(p);
2883}
2884
2885TEST(STDIO_TEST, fopen_ENOENT) {
2886 errno = 0;
2887 FILE* fp = fopen("/proc/does-not-exist", "re");
2888 ASSERT_TRUE(fp == nullptr);
2889 ASSERT_EQ(ENOENT, errno);
2890}
Elliott Hughes439ebbd2020-12-04 18:51:42 -08002891
2892static void tempnam_test(bool has_TMPDIR, const char* dir, const char* prefix, const char* re) {
2893 if (has_TMPDIR) {
2894 setenv("TMPDIR", "/my/tmp/dir", 1);
2895 } else {
2896 unsetenv("TMPDIR");
2897 }
2898 char* s1 = tempnam(dir, prefix);
2899 char* s2 = tempnam(dir, prefix);
2900 ASSERT_MATCH(s1, re);
2901 ASSERT_MATCH(s2, re);
2902 ASSERT_STRNE(s1, s2);
2903 free(s1);
2904 free(s2);
2905}
2906
2907TEST(STDIO_TEST, tempnam__system_directory_system_prefix_with_TMPDIR) {
2908 tempnam_test(true, nullptr, nullptr, "^/my/tmp/dir/.*");
2909}
2910
2911TEST(STDIO_TEST, tempnam__system_directory_system_prefix_without_TMPDIR) {
2912 tempnam_test(false, nullptr, nullptr, "^/data/local/tmp/.*");
2913}
2914
2915TEST(STDIO_TEST, tempnam__system_directory_user_prefix_with_TMPDIR) {
2916 tempnam_test(true, nullptr, "prefix", "^/my/tmp/dir/prefix.*");
2917}
2918
2919TEST(STDIO_TEST, tempnam__system_directory_user_prefix_without_TMPDIR) {
2920 tempnam_test(false, nullptr, "prefix", "^/data/local/tmp/prefix.*");
2921}
2922
2923TEST(STDIO_TEST, tempnam__user_directory_system_prefix_with_TMPDIR) {
2924 tempnam_test(true, "/a/b/c", nullptr, "^/my/tmp/dir/.*");
2925}
2926
2927TEST(STDIO_TEST, tempnam__user_directory_system_prefix_without_TMPDIR) {
2928 tempnam_test(false, "/a/b/c", nullptr, "^/a/b/c/.*");
2929}
2930
2931TEST(STDIO_TEST, tempnam__user_directory_user_prefix_with_TMPDIR) {
2932 tempnam_test(true, "/a/b/c", "prefix", "^/my/tmp/dir/prefix.*");
2933}
2934
2935TEST(STDIO_TEST, tempnam__user_directory_user_prefix_without_TMPDIR) {
2936 tempnam_test(false, "/a/b/c", "prefix", "^/a/b/c/prefix.*");
2937}
2938
2939static void tmpnam_test(char* s) {
2940 char s1[L_tmpnam], s2[L_tmpnam];
2941
2942 strcpy(s1, tmpnam(s));
2943 strcpy(s2, tmpnam(s));
2944 ASSERT_MATCH(s1, "/tmp/.*");
2945 ASSERT_MATCH(s2, "/tmp/.*");
2946 ASSERT_STRNE(s1, s2);
2947}
2948
2949TEST(STDIO_TEST, tmpnam) {
2950 tmpnam_test(nullptr);
2951}
2952
2953TEST(STDIO_TEST, tmpnam_buf) {
2954 char buf[L_tmpnam];
2955 tmpnam_test(buf);
2956}
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002957
2958TEST(STDIO_TEST, freopen_null_filename_mode) {
2959 TemporaryFile tf;
2960 FILE* fp = fopen(tf.path, "r");
2961 ASSERT_TRUE(fp != nullptr);
2962
2963 // "r" = O_RDONLY
2964 char buf[1];
2965 ASSERT_EQ(0, read(fileno(fp), buf, 1));
2966 ASSERT_EQ(-1, write(fileno(fp), "hello", 1));
2967 // "r+" = O_RDWR
2968 fp = freopen(nullptr, "r+", fp);
2969 ASSERT_EQ(0, read(fileno(fp), buf, 1));
2970 ASSERT_EQ(1, write(fileno(fp), "hello", 1));
2971 // "w" = O_WRONLY
2972 fp = freopen(nullptr, "w", fp);
2973 ASSERT_EQ(-1, read(fileno(fp), buf, 1));
2974 ASSERT_EQ(1, write(fileno(fp), "hello", 1));
2975
2976 fclose(fp);
2977}
Elliott Hughesbe78fc92022-07-28 20:58:45 +00002978
Elliott Hughes0cac2912022-08-02 18:25:22 +00002979#if defined(__LP64__)
Elliott Hughesbe78fc92022-07-28 20:58:45 +00002980static int64_t GetTotalRamGiB() {
2981 struct sysinfo si;
2982 sysinfo(&si);
2983 return (static_cast<int64_t>(si.totalram) * si.mem_unit) / 1024 / 1024 / 1024;
2984}
Elliott Hughes0cac2912022-08-02 18:25:22 +00002985#endif
Elliott Hughesbe78fc92022-07-28 20:58:45 +00002986
2987TEST(STDIO_TEST, fread_int_overflow) {
Elliott Hughes0cac2912022-08-02 18:25:22 +00002988#if defined(__LP64__)
Elliott Hughesbe78fc92022-07-28 20:58:45 +00002989 if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
2990
2991 const size_t too_big_for_an_int = 0x80000000ULL;
2992 std::vector<char> buf(too_big_for_an_int);
2993 std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/zero", "re"), fclose};
2994 ASSERT_EQ(too_big_for_an_int, fread(&buf[0], 1, too_big_for_an_int, fp.get()));
Elliott Hughes0cac2912022-08-02 18:25:22 +00002995#else
2996 GTEST_SKIP() << "32-bit can't allocate 2GiB";
2997#endif
Elliott Hughesbe78fc92022-07-28 20:58:45 +00002998}
2999
3000TEST(STDIO_TEST, fwrite_int_overflow) {
Elliott Hughes0cac2912022-08-02 18:25:22 +00003001#if defined(__LP64__)
Elliott Hughesbe78fc92022-07-28 20:58:45 +00003002 if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
3003
3004 const size_t too_big_for_an_int = 0x80000000ULL;
3005 std::vector<char> buf(too_big_for_an_int);
3006 std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/null", "we"), fclose};
3007 ASSERT_EQ(too_big_for_an_int, fwrite(&buf[0], 1, too_big_for_an_int, fp.get()));
Elliott Hughes0cac2912022-08-02 18:25:22 +00003008#else
3009 GTEST_SKIP() << "32-bit can't allocate 2GiB";
3010#endif
Elliott Hughesbe78fc92022-07-28 20:58:45 +00003011}
Elliott Hughesb813a6a2022-08-01 22:18:40 +00003012
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003013TEST(STDIO_TEST, snprintf_b_B) {
Elliott Hughese50d9d22023-04-19 16:35:40 -07003014#if defined(__BIONIC__)
Elliott Hughese50d9d22023-04-19 16:35:40 -07003015 uint8_t b = 5;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003016 EXPECT_SNPRINTF("<101>", "<%" PRIb8 ">", b);
3017 EXPECT_SNPRINTF("<101>", "<%" PRIB8 ">", b);
3018 EXPECT_SNPRINTF("<00000101>", "<%08" PRIb8 ">", b);
3019 EXPECT_SNPRINTF("<00000101>", "<%08" PRIB8 ">", b);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003020
3021 uint16_t s = 0xaaaa;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003022 EXPECT_SNPRINTF("<1010101010101010>", "<%" PRIb16 ">", s);
3023 EXPECT_SNPRINTF("<1010101010101010>", "<%" PRIB16 ">", s);
3024 EXPECT_SNPRINTF("<0b1010101010101010>", "<%#" PRIb16 ">", s);
3025 EXPECT_SNPRINTF("<0B1010101010101010>", "<%#" PRIB16 ">", s);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003026
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003027 EXPECT_SNPRINTF("<10101010101010101010101010101010>", "<%" PRIb32 ">", 0xaaaaaaaa);
3028 EXPECT_SNPRINTF("<10101010101010101010101010101010>", "<%" PRIB32 ">", 0xaaaaaaaa);
3029 EXPECT_SNPRINTF("<0b10101010101010101010101010101010>", "<%#" PRIb32 ">", 0xaaaaaaaa);
3030 EXPECT_SNPRINTF("<0B10101010101010101010101010101010>", "<%#" PRIB32 ">", 0xaaaaaaaa);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003031
3032 // clang doesn't like "%lb" (https://github.com/llvm/llvm-project/issues/62247)
3033#pragma clang diagnostic push
3034#pragma clang diagnostic ignored "-Wformat"
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003035 EXPECT_SNPRINTF("<1010101010101010101010101010101010101010101010101010101010101010>",
3036 "<%" PRIb64 ">", 0xaaaaaaaa'aaaaaaaa);
3037 EXPECT_SNPRINTF("<1010101010101010101010101010101010101010101010101010101010101010>",
3038 "<%" PRIB64 ">", 0xaaaaaaaa'aaaaaaaa);
3039 EXPECT_SNPRINTF("<0b1010101010101010101010101010101010101010101010101010101010101010>",
3040 "<%#" PRIb64 ">", 0xaaaaaaaa'aaaaaaaa);
3041 EXPECT_SNPRINTF("<0B1010101010101010101010101010101010101010101010101010101010101010>",
3042 "<%#" PRIB64 ">", 0xaaaaaaaa'aaaaaaaa);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003043#pragma clang diagnostic pop
3044
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003045 EXPECT_SNPRINTF("<0>", "<%#b>", 0);
3046 EXPECT_SNPRINTF("<0>", "<%#B>", 0);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003047#else
3048 GTEST_SKIP() << "no %b in glibc";
3049#endif
Elliott Hughesb813a6a2022-08-01 22:18:40 +00003050}
3051
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003052TEST(STDIO_TEST, swprintf_b_B) {
Elliott Hughese50d9d22023-04-19 16:35:40 -07003053#if defined(__BIONIC__)
Elliott Hughese50d9d22023-04-19 16:35:40 -07003054 uint8_t b = 5;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003055 EXPECT_SWPRINTF(L"<101>", L"<%" PRIb8 ">", b);
3056 EXPECT_SWPRINTF(L"<101>", L"<%" PRIB8 ">", b);
3057 EXPECT_SWPRINTF(L"<0b101>", L"<%#" PRIb8 ">", b);
3058 EXPECT_SWPRINTF(L"<0B101>", L"<%#" PRIB8 ">", b);
3059 EXPECT_SWPRINTF(L"<00000101>", L"<%08" PRIb8 ">", b);
3060 EXPECT_SWPRINTF(L"<00000101>", L"<%08" PRIB8 ">", b);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003061
3062 uint16_t s = 0xaaaa;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003063 EXPECT_SWPRINTF(L"<1010101010101010>", L"<%" PRIb16 ">", s);
3064 EXPECT_SWPRINTF(L"<1010101010101010>", L"<%" PRIB16 ">", s);
3065 EXPECT_SWPRINTF(L"<0b1010101010101010>", L"<%#" PRIb16 ">", s);
3066 EXPECT_SWPRINTF(L"<0B1010101010101010>", L"<%#" PRIB16 ">", s);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003067
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003068 EXPECT_SWPRINTF(L"<10101010101010101010101010101010>", L"<%" PRIb32 ">", 0xaaaaaaaa);
3069 EXPECT_SWPRINTF(L"<10101010101010101010101010101010>", L"<%" PRIB32 ">", 0xaaaaaaaa);
3070 EXPECT_SWPRINTF(L"<0b10101010101010101010101010101010>", L"<%#" PRIb32 ">", 0xaaaaaaaa);
3071 EXPECT_SWPRINTF(L"<0B10101010101010101010101010101010>", L"<%#" PRIB32 ">", 0xaaaaaaaa);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003072
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003073 // clang doesn't like "%lb" (https://github.com/llvm/llvm-project/issues/62247)
Elliott Hughese50d9d22023-04-19 16:35:40 -07003074#pragma clang diagnostic push
3075#pragma clang diagnostic ignored "-Wformat"
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003076 EXPECT_SWPRINTF(L"<1010101010101010101010101010101010101010101010101010101010101010>",
3077 L"<%" PRIb64 ">", 0xaaaaaaaa'aaaaaaaa);
3078 EXPECT_SWPRINTF(L"<1010101010101010101010101010101010101010101010101010101010101010>",
3079 L"<%" PRIB64 ">", 0xaaaaaaaa'aaaaaaaa);
3080 EXPECT_SWPRINTF(L"<0b1010101010101010101010101010101010101010101010101010101010101010>",
3081 L"<%#" PRIb64 ">", 0xaaaaaaaa'aaaaaaaa);
3082 EXPECT_SWPRINTF(L"<0B1010101010101010101010101010101010101010101010101010101010101010>",
3083 L"<%#" PRIB64 ">", 0xaaaaaaaa'aaaaaaaa);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003084#pragma clang diagnostic pop
3085
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003086 EXPECT_SWPRINTF(L"<0>", L"<%#b>", 0);
3087 EXPECT_SWPRINTF(L"<0>", L"<%#B>", 0);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003088#else
3089 GTEST_SKIP() << "no %b in glibc";
3090#endif
Elliott Hughesb813a6a2022-08-01 22:18:40 +00003091}
3092
Elliott Hughes1f462de2022-08-05 22:51:05 +00003093TEST(STDIO_TEST, scanf_i_decimal) {
3094 int i;
3095 EXPECT_EQ(1, sscanf("<123789>", "<%i>", &i));
3096 EXPECT_EQ(123789, i);
3097
3098 long long int lli;
3099 char ch;
3100 EXPECT_EQ(2, sscanf("1234567890abcdefg", "%lli%c", &lli, &ch));
3101 EXPECT_EQ(1234567890, lli);
3102 EXPECT_EQ('a', ch);
3103}
3104
3105TEST(STDIO_TEST, scanf_i_hex) {
3106 int i;
3107 EXPECT_EQ(1, sscanf("<0x123abf>", "<%i>", &i));
3108 EXPECT_EQ(0x123abf, i);
3109
3110 long long int lli;
3111 char ch;
3112 EXPECT_EQ(2, sscanf("0x1234567890abcdefg", "%lli%c", &lli, &ch));
3113 EXPECT_EQ(0x1234567890abcdefLL, lli);
3114 EXPECT_EQ('g', ch);
3115}
3116
3117TEST(STDIO_TEST, scanf_i_octal) {
3118 int i;
3119 EXPECT_EQ(1, sscanf("<01234567>", "<%i>", &i));
3120 EXPECT_EQ(01234567, i);
3121
3122 long long int lli;
3123 char ch;
3124 EXPECT_EQ(2, sscanf("010234567890abcdefg", "%lli%c", &lli, &ch));
3125 EXPECT_EQ(010234567, lli);
3126 EXPECT_EQ('8', ch);
3127}
3128
3129TEST(STDIO_TEST, scanf_i_binary) {
3130 int i;
3131 EXPECT_EQ(1, sscanf("<0b101>", "<%i>", &i));
3132 EXPECT_EQ(0b101, i);
3133
3134 long long int lli;
3135 char ch;
3136 EXPECT_EQ(2, sscanf("0b10234567890abcdefg", "%lli%c", &lli, &ch));
3137 EXPECT_EQ(0b10, lli);
3138 EXPECT_EQ('2', ch);
3139}
3140
3141TEST(STDIO_TEST, wscanf_i_decimal) {
3142 int i;
3143 EXPECT_EQ(1, swscanf(L"<123789>", L"<%i>", &i));
3144 EXPECT_EQ(123789, i);
3145
3146 long long int lli;
3147 char ch;
3148 EXPECT_EQ(2, swscanf(L"1234567890abcdefg", L"%lli%c", &lli, &ch));
3149 EXPECT_EQ(1234567890, lli);
3150 EXPECT_EQ('a', ch);
3151}
3152
3153TEST(STDIO_TEST, wscanf_i_hex) {
3154 int i;
3155 EXPECT_EQ(1, swscanf(L"<0x123abf>", L"<%i>", &i));
3156 EXPECT_EQ(0x123abf, i);
3157
3158 long long int lli;
3159 char ch;
3160 EXPECT_EQ(2, swscanf(L"0x1234567890abcdefg", L"%lli%c", &lli, &ch));
3161 EXPECT_EQ(0x1234567890abcdefLL, lli);
3162 EXPECT_EQ('g', ch);
3163}
3164
3165TEST(STDIO_TEST, wscanf_i_octal) {
3166 int i;
3167 EXPECT_EQ(1, swscanf(L"<01234567>", L"<%i>", &i));
3168 EXPECT_EQ(01234567, i);
3169
3170 long long int lli;
3171 char ch;
3172 EXPECT_EQ(2, swscanf(L"010234567890abcdefg", L"%lli%c", &lli, &ch));
3173 EXPECT_EQ(010234567, lli);
3174 EXPECT_EQ('8', ch);
3175}
3176
3177TEST(STDIO_TEST, wscanf_i_binary) {
3178 int i;
3179 EXPECT_EQ(1, swscanf(L"<0b101>", L"<%i>", &i));
3180 EXPECT_EQ(0b101, i);
3181
3182 long long int lli;
3183 char ch;
3184 EXPECT_EQ(2, swscanf(L"0b10234567890abcdefg", L"%lli%c", &lli, &ch));
3185 EXPECT_EQ(0b10, lli);
3186 EXPECT_EQ('2', ch);
3187}
3188
3189TEST(STDIO_TEST, scanf_b) {
Elliott Hughes1f462de2022-08-05 22:51:05 +00003190 int i;
3191 char ch;
3192 EXPECT_EQ(2, sscanf("<1012>", "<%b%c>", &i, &ch));
3193 EXPECT_EQ(0b101, i);
3194 EXPECT_EQ('2', ch);
3195 EXPECT_EQ(1, sscanf("<00000101>", "<%08b>", &i));
3196 EXPECT_EQ(0b00000101, i);
3197 EXPECT_EQ(1, sscanf("<0b1010>", "<%b>", &i));
3198 EXPECT_EQ(0b1010, i);
3199 EXPECT_EQ(2, sscanf("-0b", "%i%c", &i, &ch));
3200 EXPECT_EQ(0, i);
3201 EXPECT_EQ('b', ch);
Elliott Hughes1f462de2022-08-05 22:51:05 +00003202}
3203
3204TEST(STDIO_TEST, swscanf_b) {
Elliott Hughes1f462de2022-08-05 22:51:05 +00003205 int i;
3206 char ch;
3207 EXPECT_EQ(2, swscanf(L"<1012>", L"<%b%c>", &i, &ch));
3208 EXPECT_EQ(0b101, i);
3209 EXPECT_EQ('2', ch);
3210 EXPECT_EQ(1, swscanf(L"<00000101>", L"<%08b>", &i));
3211 EXPECT_EQ(0b00000101, i);
3212 EXPECT_EQ(1, swscanf(L"<0b1010>", L"<%b>", &i));
3213 EXPECT_EQ(0b1010, i);
3214 EXPECT_EQ(2, swscanf(L"-0b", L"%i%c", &i, &ch));
3215 EXPECT_EQ(0, i);
3216 EXPECT_EQ('b', ch);
Elliott Hughes1f462de2022-08-05 22:51:05 +00003217}
zijunzhao3b846ea2023-04-11 20:53:39 +00003218
3219TEST(STDIO_TEST, snprintf_w_base) {
3220#if defined(__BIONIC__)
3221#pragma clang diagnostic push
3222#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3223#pragma clang diagnostic ignored "-Wconstant-conversion"
zijunzhao3b846ea2023-04-11 20:53:39 +00003224 int8_t a = 0b101;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003225 EXPECT_SNPRINTF("<101>", "<%w8b>", a);
zijunzhao3b846ea2023-04-11 20:53:39 +00003226 int8_t b1 = 0xFF;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003227 EXPECT_SNPRINTF("<-1>", "<%w8d>", b1);
zijunzhao3b846ea2023-04-11 20:53:39 +00003228 int8_t b2 = 0x1FF;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003229 EXPECT_SNPRINTF("<-1>", "<%w8d>", b2);
zijunzhao3b846ea2023-04-11 20:53:39 +00003230 int16_t c = 0xFFFF;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003231 EXPECT_SNPRINTF("<-1>", "<%w16i>", c);
zijunzhao3b846ea2023-04-11 20:53:39 +00003232 int32_t d = 021;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003233 EXPECT_SNPRINTF("<21>", "<%w32o>", d);
zijunzhao3b846ea2023-04-11 20:53:39 +00003234 uint32_t e = -1;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003235 EXPECT_SNPRINTF("<4294967295>", "<%w32u>", e);
zijunzhao3b846ea2023-04-11 20:53:39 +00003236 int64_t f = 0x3b;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003237 EXPECT_SNPRINTF("<3b>", "<%w64x>", f);
3238 EXPECT_SNPRINTF("<3B>", "<%w64X>", f);
3239#pragma clang diagnostic pop
3240#else
3241 GTEST_SKIP() << "no %w in glibc";
3242#endif
3243}
3244
3245TEST(STDIO_TEST, swprintf_w_base) {
3246#if defined(__BIONIC__)
3247#pragma clang diagnostic push
3248#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3249#pragma clang diagnostic ignored "-Wconstant-conversion"
3250 int8_t a = 0b101;
3251 EXPECT_SWPRINTF(L"<101>", L"<%w8b>", a);
3252 int8_t b1 = 0xFF;
3253 EXPECT_SWPRINTF(L"<-1>", L"<%w8d>", b1);
3254 int8_t b2 = 0x1FF;
3255 EXPECT_SWPRINTF(L"<-1>", L"<%w8d>", b2);
3256 int16_t c = 0xFFFF;
3257 EXPECT_SWPRINTF(L"<-1>", L"<%w16i>", c);
3258 int32_t d = 021;
3259 EXPECT_SWPRINTF(L"<21>", L"<%w32o>", d);
3260 uint32_t e = -1;
3261 EXPECT_SWPRINTF(L"<4294967295>", L"<%w32u>", e);
3262 int64_t f = 0x3b;
3263 EXPECT_SWPRINTF(L"<3b>", L"<%w64x>", f);
3264 EXPECT_SWPRINTF(L"<3B>", L"<%w64X>", f);
zijunzhao3b846ea2023-04-11 20:53:39 +00003265#pragma clang diagnostic pop
3266#else
3267 GTEST_SKIP() << "no %w in glibc";
3268#endif
3269}
3270
3271TEST(STDIO_TEST, snprintf_w_arguments_reordering) {
3272#if defined(__BIONIC__)
3273#pragma clang diagnostic push
3274#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3275#pragma clang diagnostic ignored "-Wformat-extra-args"
zijunzhao3b846ea2023-04-11 20:53:39 +00003276 int32_t a = 0xaaaaaaaa;
3277 int64_t b = 0x11111111'22222222;
3278 int64_t c = 0x33333333'44444444;
3279 int64_t d = 0xaaaaaaaa'aaaaaaaa;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003280 EXPECT_SNPRINTF("<10101010101010101010101010101010 --- 3333333344444444>",
3281 "<%2$w32b --- %1$w64x>", c, a);
3282 EXPECT_SNPRINTF(
zijunzhao3b846ea2023-04-11 20:53:39 +00003283 "<1010101010101010101010101010101010101010101010101010101010101010 --- 1111111122222222 --- "
3284 "3333333344444444>",
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003285 "<%3$w64b --- %1$w64x --- %2$w64x>", b, c, d);
3286#pragma clang diagnostic pop
3287#else
3288 GTEST_SKIP() << "no %w in glibc";
3289#endif
3290}
3291
3292TEST(STDIO_TEST, swprintf_w_arguments_reordering) {
3293#if defined(__BIONIC__)
3294#pragma clang diagnostic push
3295#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3296#pragma clang diagnostic ignored "-Wformat-extra-args"
3297 int32_t a = 0xaaaaaaaa;
3298 int64_t b = 0x11111111'22222222;
3299 int64_t c = 0x33333333'44444444;
3300 int64_t d = 0xaaaaaaaa'aaaaaaaa;
3301 EXPECT_SWPRINTF(L"<10101010101010101010101010101010 --- 3333333344444444>",
3302 L"<%2$w32b --- %1$w64x>", c, a);
3303 EXPECT_SWPRINTF(
3304 L"<1010101010101010101010101010101010101010101010101010101010101010 --- 1111111122222222 --- "
3305 L"3333333344444444>",
3306 L"<%3$w64b --- %1$w64x --- %2$w64x>", b, c, d);
zijunzhao3b846ea2023-04-11 20:53:39 +00003307#pragma clang diagnostic pop
3308#else
3309 GTEST_SKIP() << "no %w in glibc";
3310#endif
3311}
3312
3313TEST(STDIO_TEST, snprintf_invalid_w_width) {
3314#if defined(__BIONIC__)
3315#pragma clang diagnostic push
3316#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3317 char buf[BUFSIZ];
3318 int32_t a = 100;
3319 EXPECT_DEATH(snprintf(buf, sizeof(buf), "%w20d", &a), "%w20 is unsupported");
3320#pragma clang diagnostic pop
3321#else
3322 GTEST_SKIP() << "no %w in glibc";
3323#endif
3324}
3325
zijunzhao3b846ea2023-04-11 20:53:39 +00003326TEST(STDIO_TEST, swprintf_invalid_w_width) {
3327#if defined(__BIONIC__)
3328#pragma clang diagnostic push
3329#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3330 wchar_t buf[BUFSIZ];
3331 int32_t a = 100;
3332 EXPECT_DEATH(swprintf(buf, sizeof(buf), L"%w20d", &a), "%w20 is unsupported");
3333#pragma clang diagnostic pop
3334#else
3335 GTEST_SKIP() << "no %w in glibc";
3336#endif
zijunzhao1fdece92023-04-25 17:37:19 +00003337}
3338
3339TEST(STDIO_TEST, snprintf_wf_base) {
3340#if defined(__BIONIC__)
3341#pragma clang diagnostic push
3342#pragma clang diagnostic ignored "-Wconstant-conversion"
3343#pragma clang diagnostic ignored "-Wformat"
3344#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
zijunzhao1fdece92023-04-25 17:37:19 +00003345 int_fast8_t a = 0b101;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003346 EXPECT_SNPRINTF("<101>", "<%wf8b>", a);
zijunzhao1fdece92023-04-25 17:37:19 +00003347 int_fast8_t b = 0x12341234'12341234;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003348 EXPECT_SNPRINTF("<34>", "<%wf8x>", b);
zijunzhao1fdece92023-04-25 17:37:19 +00003349 uint_fast16_t c = 0x11111111'22222222;
3350#if defined(__LP64__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003351 EXPECT_SNPRINTF("<1111111122222222>", "<%wf16x>", c);
zijunzhao1fdece92023-04-25 17:37:19 +00003352#else
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003353 EXPECT_SNPRINTF("<22222222>", "<%wf16x>", c);
zijunzhao1fdece92023-04-25 17:37:19 +00003354#endif
3355 int_fast32_t d = 0x33333333'44444444;
3356#if defined(__LP64__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003357 EXPECT_SNPRINTF("<3333333344444444>", "<%wf32x>", d);
zijunzhao1fdece92023-04-25 17:37:19 +00003358#else
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003359 EXPECT_SNPRINTF("<44444444>", "<%wf32x>", d);
zijunzhao1fdece92023-04-25 17:37:19 +00003360#endif
3361 int_fast64_t e = 0xaaaaaaaa'aaaaaaaa;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003362 EXPECT_SNPRINTF("<aaaaaaaaaaaaaaaa>", "<%wf64x>", e);
3363 EXPECT_SNPRINTF("<AAAAAAAAAAAAAAAA>", "<%wf64X>", e);
3364#pragma clang diagnostic pop
3365#else
3366 GTEST_SKIP() << "no %wf in glibc";
3367#endif
3368}
3369TEST(STDIO_TEST, swprintf_wf_base) {
3370#if defined(__BIONIC__)
3371#pragma clang diagnostic push
3372#pragma clang diagnostic ignored "-Wconstant-conversion"
3373#pragma clang diagnostic ignored "-Wformat"
3374#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3375 int_fast8_t a = 0b101;
3376 EXPECT_SWPRINTF(L"<101>", L"<%wf8b>", a);
3377 int_fast8_t b = 0x12341234'12341234;
3378 EXPECT_SWPRINTF(L"<34>", L"<%wf8x>", b);
3379 uint_fast16_t c = 0x11111111'22222222;
3380#if defined(__LP64__)
3381 EXPECT_SWPRINTF(L"<1111111122222222>", L"<%wf16x>", c);
3382#else
3383 EXPECT_SWPRINTF(L"<22222222>", L"<%wf16x>", c);
3384#endif
3385 int_fast32_t d = 0x33333333'44444444;
3386#if defined(__LP64__)
3387 EXPECT_SWPRINTF(L"<3333333344444444>", L"<%wf32x>", d);
3388#else
3389 EXPECT_SWPRINTF(L"<44444444>", L"<%wf32x>", d);
3390#endif
3391 int_fast64_t e = 0xaaaaaaaa'aaaaaaaa;
3392 EXPECT_SWPRINTF(L"<aaaaaaaaaaaaaaaa>", L"<%wf64x>", e);
3393 EXPECT_SWPRINTF(L"<AAAAAAAAAAAAAAAA>", L"<%wf64X>", e);
zijunzhao1fdece92023-04-25 17:37:19 +00003394#pragma clang diagnostic pop
3395#else
3396 GTEST_SKIP() << "no %wf in glibc";
3397#endif
3398}
3399
3400TEST(STDIO_TEST, snprintf_wf_arguments_reordering) {
3401#if defined(__BIONIC__)
3402#pragma clang diagnostic push
3403#pragma clang diagnostic ignored "-Wconstant-conversion"
3404#pragma clang diagnostic ignored "-Wformat"
3405#pragma clang diagnostic ignored "-Wformat-extra-args"
3406#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
zijunzhao1fdece92023-04-25 17:37:19 +00003407 int_fast16_t a = 0x11111111'22222222;
3408 int_fast32_t b = 0x33333333'44444444;
3409 int_fast32_t c = 0xaaaaaaaa'aaaaaaaa;
3410#if defined(__LP64__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003411 EXPECT_SNPRINTF(
zijunzhao1fdece92023-04-25 17:37:19 +00003412 "<3333333344444444 --- 1010101010101010101010101010101010101010101010101010101010101010>",
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003413 "<%2$wf32x --- %1$wf32b>", c, b);
3414
3415 EXPECT_SNPRINTF(
zijunzhao1fdece92023-04-25 17:37:19 +00003416 "<1010101010101010101010101010101010101010101010101010101010101010 --- 1111111122222222 --- "
3417 "3333333344444444>",
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003418 "<%3$wf32b --- %1$wf16x --- %2$wf32x>", a, b, c);
zijunzhao1fdece92023-04-25 17:37:19 +00003419#else
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003420 EXPECT_SNPRINTF("<44444444 --- 10101010101010101010101010101010>", "<%2$wf32x --- %1$wf32b>", c,
3421 b);
3422 EXPECT_SNPRINTF("<10101010101010101010101010101010 --- 22222222 --- 44444444>",
3423 "<%3$wf32b --- %1$wf16x --- %2$wf32x>", a, b, c);
3424#endif
3425#pragma clang diagnostic pop
3426#else
3427 GTEST_SKIP() << "no %w in glibc";
3428#endif
3429}
3430
3431TEST(STDIO_TEST, swprintf_wf_arguments_reordering) {
3432#if defined(__BIONIC__)
3433#pragma clang diagnostic push
3434#pragma clang diagnostic ignored "-Wconstant-conversion"
3435#pragma clang diagnostic ignored "-Wformat"
3436#pragma clang diagnostic ignored "-Wformat-extra-args"
3437#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3438 int_fast16_t a = 0x11111111'22222222;
3439 int_fast32_t b = 0x33333333'44444444;
3440 int_fast32_t c = 0xaaaaaaaa'aaaaaaaa;
3441#if defined(__LP64__)
3442 EXPECT_SWPRINTF(
3443 L"<3333333344444444 --- 1010101010101010101010101010101010101010101010101010101010101010>",
3444 L"<%2$wf32x --- %1$wf32b>", c, b);
3445
3446 EXPECT_SWPRINTF(
3447 L"<1010101010101010101010101010101010101010101010101010101010101010 --- 1111111122222222 --- "
3448 L"3333333344444444>",
3449 L"<%3$wf32b --- %1$wf16x --- %2$wf32x>", a, b, c);
3450#else
3451 EXPECT_SWPRINTF(L"<44444444 --- 10101010101010101010101010101010>", L"<%2$wf32x --- %1$wf32b>", c,
3452 b);
3453 EXPECT_SWPRINTF(L"<10101010101010101010101010101010 --- 22222222 --- 44444444>",
3454 L"<%3$wf32b --- %1$wf16x --- %2$wf32x>", a, b, c);
zijunzhao1fdece92023-04-25 17:37:19 +00003455#endif
3456#pragma clang diagnostic pop
3457#else
3458 GTEST_SKIP() << "no %w in glibc";
3459#endif
3460}
3461
3462TEST(STDIO_TEST, snprintf_invalid_wf_width) {
3463#if defined(__BIONIC__)
3464#pragma clang diagnostic push
3465#pragma clang diagnostic ignored "-Wformat"
3466#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3467 char buf[BUFSIZ];
3468 int_fast32_t a = 100;
3469 EXPECT_DEATH(snprintf(buf, sizeof(buf), "%wf20d", &a), "%wf20 is unsupported");
3470#pragma clang diagnostic pop
3471#else
3472 GTEST_SKIP() << "no %w in glibc";
3473#endif
3474}
3475
zijunzhao1fdece92023-04-25 17:37:19 +00003476TEST(STDIO_TEST, swprintf_invalid_wf_width) {
3477#if defined(__BIONIC__)
3478#pragma clang diagnostic push
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003479#pragma clang diagnostic ignored "-Wformat"
zijunzhao1fdece92023-04-25 17:37:19 +00003480#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3481 wchar_t buf[BUFSIZ];
3482 int_fast32_t a = 100;
3483 EXPECT_DEATH(swprintf(buf, sizeof(buf), L"%wf20d", &a), "%wf20 is unsupported");
3484#pragma clang diagnostic pop
3485#else
3486 GTEST_SKIP() << "no %w in glibc";
3487#endif
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003488}
zijunzhao78904842023-05-09 00:54:00 +00003489
3490TEST(STDIO_TEST, sscanf_w_base) {
3491#if defined(__BIONIC__)
3492#pragma clang diagnostic push
3493#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3494 int8_t a;
3495 EXPECT_EQ(1, sscanf("<0b101>", "<%w8b>", &a));
3496 EXPECT_EQ(0b101, a);
3497 int8_t b1;
3498 EXPECT_EQ(1, sscanf("<0xFF>", "<%w8i>", &b1));
3499 EXPECT_EQ(-1, b1);
3500 int8_t b2;
3501 EXPECT_EQ(1, sscanf("<0x1FF>", "<%w8i>", &b2));
3502 EXPECT_EQ(-1, b2);
3503 int16_t c1;
3504 EXPECT_EQ(1, sscanf("<0xFFFF>", "<%w16i>", &c1));
3505 EXPECT_EQ(-1, c1);
3506 uint16_t c2;
3507 EXPECT_EQ(1, sscanf("<64>", "<%w16d>", &c2));
3508 EXPECT_EQ(64, c2);
3509 int32_t d;
3510 EXPECT_EQ(1, sscanf("<021>", "<%w32o>", &d));
3511 EXPECT_EQ(021, d);
3512 uint32_t e;
3513 EXPECT_EQ(1, sscanf("<-1>", "<%w32u>", &e));
3514 EXPECT_EQ(4294967295, e);
3515 int64_t f;
3516 EXPECT_EQ(1, sscanf("<0x3b>", "<%w64x>", &f));
3517 EXPECT_EQ(0x3b, f);
3518 EXPECT_EQ(1, sscanf("<0x3b>", "<%w64X>", &f));
3519 EXPECT_EQ(0x3B, f);
3520#pragma clang diagnostic pop
3521#else
3522 GTEST_SKIP() << "no %w in glibc";
3523#endif
3524}
3525
3526TEST(STDIO_TEST, sscanf_w_combination) {
3527#if defined(__BIONIC__)
3528#pragma clang diagnostic push
3529#pragma clang diagnostic ignored "-Wformat"
3530#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3531#pragma clang diagnostic ignored "-Wformat-extra-args"
3532 uint32_t a;
3533 int64_t b;
3534 char c;
3535
3536 EXPECT_EQ(3, sscanf("<0b10101010101010101010101010101010 0x3333333344444444 1>",
3537 "<%w32b %w64x %c>", &a, &b, &c));
3538 EXPECT_EQ(0xaaaaaaaa, a);
3539 EXPECT_EQ(0x3333333344444444, b);
3540 EXPECT_EQ('1', c);
3541#pragma clang diagnostic pop
3542#else
3543 GTEST_SKIP() << "no %w in glibc";
3544#endif
3545}
3546
3547TEST(STDIO_TEST, sscanf_invalid_w_width) {
3548#if defined(__BIONIC__)
3549#pragma clang diagnostic push
3550#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3551 int32_t a;
3552 EXPECT_DEATH(sscanf("<100>", "<%w20d>", &a), "%w20 is unsupported");
3553#pragma clang diagnostic pop
3554#else
3555 GTEST_SKIP() << "no %w in glibc";
3556#endif
3557}
3558
3559TEST(STDIO_TEST, swscanf_w_base) {
3560#if defined(__BIONIC__)
3561#pragma clang diagnostic push
3562#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3563 int8_t a;
3564 EXPECT_EQ(1, swscanf(L"<0b101>", L"<%w8b>", &a));
3565 EXPECT_EQ(0b101, a);
3566 int8_t b1;
3567 EXPECT_EQ(1, swscanf(L"<0xFF>", L"<%w8i>", &b1));
3568 EXPECT_EQ(-1, b1);
3569 int8_t b2;
3570 EXPECT_EQ(1, swscanf(L"<0x1FF>", L"<%w8i>", &b2));
3571 EXPECT_EQ(-1, b2);
3572 int16_t c1;
3573 EXPECT_EQ(1, swscanf(L"<0xFFFF>", L"<%w16i>", &c1));
3574 EXPECT_EQ(-1, c1);
3575 uint16_t c2;
3576 EXPECT_EQ(1, swscanf(L"<64>", L"<%w16d>", &c2));
3577 EXPECT_EQ(64, c2);
3578 int32_t d;
3579 EXPECT_EQ(1, swscanf(L"<021>", L"<%w32o>", &d));
3580 EXPECT_EQ(021, d);
3581 uint32_t e;
3582 EXPECT_EQ(1, swscanf(L"<-1>", L"<%w32u>", &e));
3583 EXPECT_EQ(4294967295, e);
3584 int64_t f;
3585 EXPECT_EQ(1, swscanf(L"<0x3b>", L"<%w64x>", &f));
3586 EXPECT_EQ(0x3b, f);
3587 EXPECT_EQ(1, swscanf(L"<0x3b>", L"<%w64X>", &f));
3588 EXPECT_EQ(0x3B, f);
3589#pragma clang diagnostic pop
3590#else
3591 GTEST_SKIP() << "no %w in glibc";
3592#endif
3593}
3594
3595TEST(STDIO_TEST, swscanf_w_combination) {
3596#if defined(__BIONIC__)
3597#pragma clang diagnostic push
3598#pragma clang diagnostic ignored "-Wformat"
3599#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3600#pragma clang diagnostic ignored "-Wformat-extra-args"
3601 uint32_t a;
3602 int64_t b;
3603 char c;
3604
3605 EXPECT_EQ(3, swscanf(L"<0b10101010101010101010101010101010 0x3333333344444444 1>",
3606 L"<%w32b %w64x %c>", &a, &b, &c));
3607 EXPECT_EQ(0xaaaaaaaa, a);
3608 EXPECT_EQ(0x3333333344444444, b);
3609 EXPECT_EQ('1', c);
3610#pragma clang diagnostic pop
3611#else
3612 GTEST_SKIP() << "no %w in glibc";
3613#endif
3614}
3615
3616TEST(STDIO_TEST, swscanf_invalid_w_width) {
3617#if defined(__BIONIC__)
3618#pragma clang diagnostic push
3619#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3620 int32_t a;
3621 EXPECT_DEATH(swscanf(L"<100>", L"<%w20d>", &a), "%w20 is unsupported");
3622#pragma clang diagnostic pop
3623#else
3624 GTEST_SKIP() << "no %w in glibc";
3625#endif
3626}