blob: bfe8406445d5305d035ecbf166bcaafdddb2616b [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 Hughes95646e62023-09-21 14:11:19 -0700223 ASSERT_ERRNO(0);
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 Hughes95646e62023-09-21 14:11:19 -0700242 ASSERT_ERRNO(EINVAL);
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 Hughes95646e62023-09-21 14:11:19 -0700247 ASSERT_ERRNO(EINVAL);
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 Hughes95646e62023-09-21 14:11:19 -0700296 ASSERT_ERRNO(0);
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 Hughes95646e62023-09-21 14:11:19 -0700315 ASSERT_ERRNO(EINVAL);
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 Hughes95646e62023-09-21 14:11:19 -0700320 ASSERT_ERRNO(EINVAL);
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", '!'));
Elliott Hughes95646e62023-09-21 14:11:19 -0700919 ASSERT_ERRNO(ENOMEM);
Elliott Hughes8200e552016-02-05 21:57:37 -0800920}
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", '!'));
Elliott Hughes95646e62023-09-21 14:11:19 -0700934 ASSERT_ERRNO(ENOMEM);
Elliott Hughes8fd4e962023-05-08 17:29:41 -0700935}
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) {
Christopher Ferris15c22cd2023-07-24 17:42:17 -07001052 // Use a realtime signal to avoid creating a tombstone when running.
1053 std::string cmd = android::base::StringPrintf("kill -%d $$", SIGRTMIN);
1054 FILE* fp = popen(cmd.c_str(), "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001055 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -07001056 int status = pclose(fp);
1057 EXPECT_TRUE(WIFSIGNALED(status));
Christopher Ferris15c22cd2023-07-24 17:42:17 -07001058 EXPECT_EQ(SIGRTMIN, WTERMSIG(status));
Elliott Hughes468efc82018-07-10 14:39:49 -07001059}
1060
Christopher Ferris13f26a72016-01-13 13:47:58 -08001061TEST(STDIO_TEST, getc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001062 FILE* fp = fopen("/proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001063 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001064 ASSERT_EQ('L', getc(fp));
1065 ASSERT_EQ('i', getc(fp));
1066 ASSERT_EQ('n', getc(fp));
1067 ASSERT_EQ('u', getc(fp));
1068 ASSERT_EQ('x', getc(fp));
1069 fclose(fp);
1070}
1071
Christopher Ferris13f26a72016-01-13 13:47:58 -08001072TEST(STDIO_TEST, putc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001073 FILE* fp = fopen("/proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001074 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b05c8e2013-04-11 13:54:48 -07001075 ASSERT_EQ(EOF, putc('x', fp));
1076 fclose(fp);
1077}
Elliott Hughes603332f2014-03-12 17:10:41 -07001078
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001079TEST(STDIO_TEST, sscanf_swscanf) {
1080 struct stuff {
1081 char s1[123];
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001082 int i1, i2;
1083 char cs1[3];
1084 char s2[3];
1085 char c1;
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001086 double d1;
1087 float f1;
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001088 char s3[123];
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001089
1090 void Check() {
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001091 EXPECT_STREQ("hello", s1);
1092 EXPECT_EQ(123, i1);
1093 EXPECT_EQ(456, i2);
1094 EXPECT_EQ('a', cs1[0]);
1095 EXPECT_EQ('b', cs1[1]);
1096 EXPECT_EQ('x', cs1[2]); // No terminating NUL.
1097 EXPECT_STREQ("AB", s2); // Terminating NUL.
1098 EXPECT_EQ('!', c1);
1099 EXPECT_DOUBLE_EQ(1.23, d1);
1100 EXPECT_FLOAT_EQ(9.0f, f1);
1101 EXPECT_STREQ("world", s3);
Elliott Hughes7f0849f2016-08-26 16:17:17 -07001102 }
1103 } s;
1104
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001105 memset(&s, 'x', sizeof(s));
1106 ASSERT_EQ(9, sscanf(" hello 123 456abAB! 1.23 0x1.2p3 world",
1107 "%s %i%i%2c%[A-Z]%c %lf %f %s",
1108 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 -07001109 s.Check();
1110
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001111 memset(&s, 'x', sizeof(s));
1112 ASSERT_EQ(9, swscanf(L" hello 123 456abAB! 1.23 0x1.2p3 world",
1113 L"%s %i%i%2c%[A-Z]%c %lf %f %s",
1114 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 -07001115 s.Check();
Elliott Hughes603332f2014-03-12 17:10:41 -07001116}
Elliott Hughes53b24382014-05-02 18:29:25 -07001117
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001118template <typename T>
1119static void CheckScanf(int sscanf_fn(const T*, const T*, ...),
1120 const T* input, const T* fmt,
1121 int expected_count, const char* expected_string) {
1122 char buf[256] = {};
1123 ASSERT_EQ(expected_count, sscanf_fn(input, fmt, &buf)) << fmt;
1124 ASSERT_STREQ(expected_string, buf) << fmt;
1125}
1126
1127TEST(STDIO_TEST, sscanf_ccl) {
1128 // `abc` is just those characters.
1129 CheckScanf(sscanf, "abcd", "%[abc]", 1, "abc");
1130 // `a-c` is the range 'a' .. 'c'.
1131 CheckScanf(sscanf, "abcd", "%[a-c]", 1, "abc");
1132 CheckScanf(sscanf, "-d", "%[a-c]", 0, "");
1133 CheckScanf(sscanf, "ac-bAd", "%[a--c]", 1, "ac-bA");
1134 // `a-c-e` is equivalent to `a-e`.
1135 CheckScanf(sscanf, "abcdefg", "%[a-c-e]", 1, "abcde");
1136 // `e-a` is equivalent to `ae-` (because 'e' > 'a').
1137 CheckScanf(sscanf, "-a-e-b", "%[e-a]", 1, "-a-e-");
1138 // An initial '^' negates the set.
1139 CheckScanf(sscanf, "abcde", "%[^d]", 1, "abc");
1140 CheckScanf(sscanf, "abcdefgh", "%[^c-d]", 1, "ab");
1141 CheckScanf(sscanf, "hgfedcba", "%[^c-d]", 1, "hgfe");
1142 // The first character may be ']' or '-' without being special.
1143 CheckScanf(sscanf, "[[]]x", "%[][]", 1, "[[]]");
1144 CheckScanf(sscanf, "-a-x", "%[-a]", 1, "-a-");
1145 // The last character may be '-' without being special.
1146 CheckScanf(sscanf, "-a-x", "%[a-]", 1, "-a-");
1147 // X--Y is [X--] + Y, not [X--] + [--Y] (a bug in my initial implementation).
1148 CheckScanf(sscanf, "+,-/.", "%[+--/]", 1, "+,-/");
1149}
1150
1151TEST(STDIO_TEST, swscanf_ccl) {
1152 // `abc` is just those characters.
1153 CheckScanf(swscanf, L"abcd", L"%[abc]", 1, "abc");
1154 // `a-c` is the range 'a' .. 'c'.
1155 CheckScanf(swscanf, L"abcd", L"%[a-c]", 1, "abc");
1156 CheckScanf(swscanf, L"-d", L"%[a-c]", 0, "");
1157 CheckScanf(swscanf, L"ac-bAd", L"%[a--c]", 1, "ac-bA");
1158 // `a-c-e` is equivalent to `a-e`.
1159 CheckScanf(swscanf, L"abcdefg", L"%[a-c-e]", 1, "abcde");
1160 // `e-a` is equivalent to `ae-` (because 'e' > 'a').
1161 CheckScanf(swscanf, L"-a-e-b", L"%[e-a]", 1, "-a-e-");
1162 // An initial '^' negates the set.
1163 CheckScanf(swscanf, L"abcde", L"%[^d]", 1, "abc");
1164 CheckScanf(swscanf, L"abcdefgh", L"%[^c-d]", 1, "ab");
1165 CheckScanf(swscanf, L"hgfedcba", L"%[^c-d]", 1, "hgfe");
1166 // The first character may be ']' or '-' without being special.
1167 CheckScanf(swscanf, L"[[]]x", L"%[][]", 1, "[[]]");
1168 CheckScanf(swscanf, L"-a-x", L"%[-a]", 1, "-a-");
1169 // The last character may be '-' without being special.
1170 CheckScanf(swscanf, L"-a-x", L"%[a-]", 1, "-a-");
1171 // X--Y is [X--] + Y, not [X--] + [--Y] (a bug in my initial implementation).
1172 CheckScanf(swscanf, L"+,-/.", L"%[+--/]", 1, "+,-/");
1173}
1174
Elliott Hughes38e4aef2018-01-18 10:21:29 -08001175template <typename T1, typename T2>
1176static void CheckScanfM(int sscanf_fn(const T1*, const T1*, ...),
1177 const T1* input, const T1* fmt,
1178 int expected_count, const T2* expected_string) {
1179 T2* result = nullptr;
1180 ASSERT_EQ(expected_count, sscanf_fn(input, fmt, &result)) << fmt;
1181 if (expected_string == nullptr) {
1182 ASSERT_EQ(nullptr, result);
1183 } else {
1184 ASSERT_STREQ(expected_string, result) << fmt;
1185 }
1186 free(result);
1187}
1188
1189TEST(STDIO_TEST, sscanf_mc) {
1190 char* p1 = nullptr;
1191 char* p2 = nullptr;
1192 ASSERT_EQ(2, sscanf("hello", "%mc%mc", &p1, &p2));
1193 ASSERT_EQ('h', *p1);
1194 ASSERT_EQ('e', *p2);
1195 free(p1);
1196 free(p2);
1197
1198 p1 = nullptr;
1199 ASSERT_EQ(1, sscanf("hello", "%4mc", &p1));
1200 ASSERT_EQ('h', p1[0]);
1201 ASSERT_EQ('e', p1[1]);
1202 ASSERT_EQ('l', p1[2]);
1203 ASSERT_EQ('l', p1[3]);
1204 free(p1);
1205
1206 p1 = nullptr;
1207 ASSERT_EQ(1, sscanf("hello world", "%30mc", &p1));
1208 ASSERT_EQ('h', p1[0]);
1209 ASSERT_EQ('e', p1[1]);
1210 ASSERT_EQ('l', p1[2]);
1211 ASSERT_EQ('l', p1[3]);
1212 ASSERT_EQ('o', p1[4]);
1213 free(p1);
1214}
1215
Elliott Hughes38e4aef2018-01-18 10:21:29 -08001216TEST(STDIO_TEST, sscanf_mlc) {
1217 // This is so useless that clang doesn't even believe it exists...
1218#pragma clang diagnostic push
1219#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
1220#pragma clang diagnostic ignored "-Wformat-extra-args"
1221
1222 wchar_t* p1 = nullptr;
1223 wchar_t* p2 = nullptr;
1224 ASSERT_EQ(2, sscanf("hello", "%mlc%mlc", &p1, &p2));
1225 ASSERT_EQ(L'h', *p1);
1226 ASSERT_EQ(L'e', *p2);
1227 free(p1);
1228 free(p2);
1229
1230 p1 = nullptr;
1231 ASSERT_EQ(1, sscanf("hello", "%4mlc", &p1));
1232 ASSERT_EQ(L'h', p1[0]);
1233 ASSERT_EQ(L'e', p1[1]);
1234 ASSERT_EQ(L'l', p1[2]);
1235 ASSERT_EQ(L'l', p1[3]);
1236 free(p1);
1237
1238 p1 = nullptr;
1239 ASSERT_EQ(1, sscanf("hello world", "%30mlc", &p1));
1240 ASSERT_EQ(L'h', p1[0]);
1241 ASSERT_EQ(L'e', p1[1]);
1242 ASSERT_EQ(L'l', p1[2]);
1243 ASSERT_EQ(L'l', p1[3]);
1244 ASSERT_EQ(L'o', p1[4]);
1245 free(p1);
1246#pragma clang diagnostic pop
1247}
1248
Elliott Hughes38e4aef2018-01-18 10:21:29 -08001249TEST(STDIO_TEST, sscanf_ms) {
1250 CheckScanfM(sscanf, "hello", "%ms", 1, "hello");
1251 CheckScanfM(sscanf, "hello", "%4ms", 1, "hell");
1252 CheckScanfM(sscanf, "hello world", "%30ms", 1, "hello");
1253}
1254
1255TEST(STDIO_TEST, sscanf_mls) {
1256 CheckScanfM(sscanf, "hello", "%mls", 1, L"hello");
1257 CheckScanfM(sscanf, "hello", "%4mls", 1, L"hell");
1258 CheckScanfM(sscanf, "hello world", "%30mls", 1, L"hello");
1259}
1260
1261TEST(STDIO_TEST, sscanf_m_ccl) {
1262 CheckScanfM(sscanf, "hello", "%m[a-z]", 1, "hello");
1263 CheckScanfM(sscanf, "hello", "%4m[a-z]", 1, "hell");
1264 CheckScanfM(sscanf, "hello world", "%30m[a-z]", 1, "hello");
1265}
1266
1267TEST(STDIO_TEST, sscanf_ml_ccl) {
1268 CheckScanfM(sscanf, "hello", "%ml[a-z]", 1, L"hello");
1269 CheckScanfM(sscanf, "hello", "%4ml[a-z]", 1, L"hell");
1270 CheckScanfM(sscanf, "hello world", "%30ml[a-z]", 1, L"hello");
1271}
1272
1273TEST(STDIO_TEST, sscanf_ls) {
1274 wchar_t w[32] = {};
1275 ASSERT_EQ(1, sscanf("hello world", "%ls", w));
1276 ASSERT_EQ(L"hello", std::wstring(w));
1277}
1278
1279TEST(STDIO_TEST, sscanf_ls_suppress) {
1280 ASSERT_EQ(0, sscanf("hello world", "%*ls %*ls"));
1281}
1282
1283TEST(STDIO_TEST, sscanf_ls_n) {
1284 setlocale(LC_ALL, "C.UTF-8");
1285 wchar_t w[32] = {};
1286 int pos = 0;
1287 ASSERT_EQ(1, sscanf("\xc4\x80", "%ls%n", w, &pos));
1288 ASSERT_EQ(static_cast<wchar_t>(256), w[0]);
1289 ASSERT_EQ(2, pos);
1290}
1291
1292TEST(STDIO_TEST, sscanf_ls_realloc) {
1293 // This is so useless that clang doesn't even believe it exists...
1294#pragma clang diagnostic push
1295#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
1296#pragma clang diagnostic ignored "-Wformat-extra-args"
1297 wchar_t* p1 = nullptr;
1298 wchar_t* p2 = nullptr;
1299 ASSERT_EQ(2, sscanf("1234567890123456789012345678901234567890 world", "%mls %mls", &p1, &p2));
1300 ASSERT_EQ(L"1234567890123456789012345678901234567890", std::wstring(p1));
1301 ASSERT_EQ(L"world", std::wstring(p2));
1302#pragma clang diagnostic pop
1303}
1304
Elliott Hughesbf9cb9e2017-12-11 12:39:01 -08001305// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=202240
1306TEST(STDIO_TEST, scanf_wscanf_EOF) {
1307 EXPECT_EQ(0, sscanf("b", "ab"));
1308 EXPECT_EQ(EOF, sscanf("", "a"));
1309 EXPECT_EQ(0, swscanf(L"b", L"ab"));
1310 EXPECT_EQ(EOF, swscanf(L"", L"a"));
1311}
1312
1313TEST(STDIO_TEST, scanf_invalid_UTF8) {
1314#if 0 // TODO: more tests invented during code review; no regressions, so fix later.
1315 char buf[BUFSIZ];
1316 wchar_t wbuf[BUFSIZ];
1317
1318 memset(buf, 0, sizeof(buf));
1319 memset(wbuf, 0, sizeof(wbuf));
1320 EXPECT_EQ(0, sscanf("\xc0" " foo", "%ls %s", wbuf, buf));
1321#endif
1322}
1323
1324TEST(STDIO_TEST, scanf_no_match_no_termination) {
1325 char buf[4] = "x";
1326 EXPECT_EQ(0, sscanf("d", "%[abc]", buf));
1327 EXPECT_EQ('x', buf[0]);
1328 EXPECT_EQ(0, swscanf(L"d", L"%[abc]", buf));
1329 EXPECT_EQ('x', buf[0]);
1330
1331 wchar_t wbuf[4] = L"x";
1332 EXPECT_EQ(0, swscanf(L"d", L"%l[abc]", wbuf));
1333 EXPECT_EQ(L'x', wbuf[0]);
1334
1335 EXPECT_EQ(EOF, sscanf("", "%s", buf));
1336 EXPECT_EQ('x', buf[0]);
1337
1338 EXPECT_EQ(EOF, swscanf(L"", L"%ls", wbuf));
1339 EXPECT_EQ(L'x', wbuf[0]);
1340}
1341
1342TEST(STDIO_TEST, scanf_wscanf_wide_character_class) {
1343#if 0 // TODO: more tests invented during code review; no regressions, so fix later.
1344 wchar_t buf[BUFSIZ];
1345
1346 // A wide character shouldn't match an ASCII-only class for scanf or wscanf.
1347 memset(buf, 0, sizeof(buf));
1348 EXPECT_EQ(1, sscanf("xĀyz", "%l[xy]", buf));
1349 EXPECT_EQ(L"x"s, std::wstring(buf));
1350 memset(buf, 0, sizeof(buf));
1351 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[xy]", buf));
1352 EXPECT_EQ(L"x"s, std::wstring(buf));
1353
1354 // Even if scanf has wide characters in a class, they won't match...
1355 // TODO: is that a bug?
1356 memset(buf, 0, sizeof(buf));
1357 EXPECT_EQ(1, sscanf("xĀyz", "%l[xĀy]", buf));
1358 EXPECT_EQ(L"x"s, std::wstring(buf));
1359 // ...unless you use wscanf.
1360 memset(buf, 0, sizeof(buf));
1361 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[xĀy]", buf));
1362 EXPECT_EQ(L"xĀy"s, std::wstring(buf));
1363
1364 // Negation only covers ASCII for scanf...
1365 memset(buf, 0, sizeof(buf));
1366 EXPECT_EQ(1, sscanf("xĀyz", "%l[^ab]", buf));
1367 EXPECT_EQ(L"x"s, std::wstring(buf));
1368 // ...but covers wide characters for wscanf.
1369 memset(buf, 0, sizeof(buf));
1370 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[^ab]", buf));
1371 EXPECT_EQ(L"xĀyz"s, std::wstring(buf));
1372
1373 // We already determined that non-ASCII characters are ignored in scanf classes.
1374 memset(buf, 0, sizeof(buf));
1375 EXPECT_EQ(1, sscanf("x"
1376 "\xc4\x80" // Matches a byte from each wide char in the class.
1377 "\xc6\x82" // Neither byte is in the class.
1378 "yz",
1379 "%l[xy" "\xc5\x80" "\xc4\x81" "]", buf));
1380 EXPECT_EQ(L"x", std::wstring(buf));
1381 // bionic and glibc both behave badly for wscanf, so let's call it right for now...
1382 memset(buf, 0, sizeof(buf));
1383 EXPECT_EQ(1, swscanf(L"x"
1384 L"\xc4\x80"
1385 L"\xc6\x82"
1386 L"yz",
1387 L"%l[xy" L"\xc5\x80" L"\xc4\x81" L"]", buf));
1388 // Note that this isn't L"xĀ" --- although the *bytes* matched, they're
1389 // not put back together as a wide character.
1390 EXPECT_EQ(L"x" L"\xc4" L"\x80", std::wstring(buf));
1391#endif
1392}
1393
Christopher Ferris13f26a72016-01-13 13:47:58 -08001394TEST(STDIO_TEST, cantwrite_EBADF) {
Elliott Hughes53b24382014-05-02 18:29:25 -07001395 // If we open a file read-only...
1396 FILE* fp = fopen("/proc/version", "r");
1397
1398 // ...all attempts to write to that file should return failure.
1399
1400 // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
1401 // glibc gets the wide-character functions wrong.
1402
1403 errno = 0;
1404 EXPECT_EQ(EOF, putc('x', fp));
Elliott Hughes95646e62023-09-21 14:11:19 -07001405 EXPECT_ERRNO(EBADF);
Elliott Hughes53b24382014-05-02 18:29:25 -07001406
1407 errno = 0;
1408 EXPECT_EQ(EOF, fprintf(fp, "hello"));
Elliott Hughes95646e62023-09-21 14:11:19 -07001409 EXPECT_ERRNO(EBADF);
Elliott Hughes53b24382014-05-02 18:29:25 -07001410
1411 errno = 0;
1412 EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
Elliott Hughes063525c2014-05-13 11:19:57 -07001413#if defined(__BIONIC__)
Elliott Hughes95646e62023-09-21 14:11:19 -07001414 EXPECT_ERRNO(EBADF);
Elliott Hughes53b24382014-05-02 18:29:25 -07001415#endif
1416
1417 errno = 0;
Elliott Hughes53b24382014-05-02 18:29:25 -07001418 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
Elliott Hughes95646e62023-09-21 14:11:19 -07001419 EXPECT_ERRNO(EBADF);
Elliott Hughes53b24382014-05-02 18:29:25 -07001420
1421 errno = 0;
1422 EXPECT_EQ(EOF, fputs("hello", fp));
Elliott Hughes95646e62023-09-21 14:11:19 -07001423 EXPECT_ERRNO(EBADF);
Elliott Hughes53b24382014-05-02 18:29:25 -07001424
1425 errno = 0;
1426 EXPECT_EQ(WEOF, fputwc(L'x', fp));
Elliott Hughes063525c2014-05-13 11:19:57 -07001427#if defined(__BIONIC__)
Elliott Hughes95646e62023-09-21 14:11:19 -07001428 EXPECT_ERRNO(EBADF);
Elliott Hughes53b24382014-05-02 18:29:25 -07001429#endif
1430}
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001431
1432// Tests that we can only have a consistent and correct fpos_t when using
1433// f*pos functions (i.e. fpos doesn't get inside a multi byte character).
Christopher Ferris13f26a72016-01-13 13:47:58 -08001434TEST(STDIO_TEST, consistent_fpos_t) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001435 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
1436 uselocale(LC_GLOBAL_LOCALE);
1437
1438 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -07001439 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001440
1441 wchar_t mb_one_bytes = L'h';
1442 wchar_t mb_two_bytes = 0x00a2;
1443 wchar_t mb_three_bytes = 0x20ac;
1444 wchar_t mb_four_bytes = 0x24b62;
1445
1446 // Write to file.
1447 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp)));
1448 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
1449 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
1450 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
1451
1452 rewind(fp);
1453
1454 // Record each character position.
1455 fpos_t pos1;
1456 fpos_t pos2;
1457 fpos_t pos3;
1458 fpos_t pos4;
1459 fpos_t pos5;
1460 EXPECT_EQ(0, fgetpos(fp, &pos1));
1461 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
1462 EXPECT_EQ(0, fgetpos(fp, &pos2));
1463 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1464 EXPECT_EQ(0, fgetpos(fp, &pos3));
1465 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
1466 EXPECT_EQ(0, fgetpos(fp, &pos4));
1467 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
1468 EXPECT_EQ(0, fgetpos(fp, &pos5));
1469
Elliott Hughes063525c2014-05-13 11:19:57 -07001470#if defined(__BIONIC__)
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001471 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD
1472 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In
1473 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE
1474 // structure.
1475 ASSERT_EQ(0, static_cast<off_t>(pos1));
1476 ASSERT_EQ(1, static_cast<off_t>(pos2));
1477 ASSERT_EQ(3, static_cast<off_t>(pos3));
1478 ASSERT_EQ(6, static_cast<off_t>(pos4));
1479 ASSERT_EQ(10, static_cast<off_t>(pos5));
1480#endif
1481
1482 // Exercise back and forth movements of the position.
1483 ASSERT_EQ(0, fsetpos(fp, &pos2));
1484 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1485 ASSERT_EQ(0, fsetpos(fp, &pos1));
1486 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
1487 ASSERT_EQ(0, fsetpos(fp, &pos4));
1488 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
1489 ASSERT_EQ(0, fsetpos(fp, &pos3));
1490 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
1491 ASSERT_EQ(0, fsetpos(fp, &pos5));
1492 ASSERT_EQ(WEOF, fgetwc(fp));
1493
1494 fclose(fp);
1495}
1496
1497// Exercise the interaction between fpos and seek.
Christopher Ferris13f26a72016-01-13 13:47:58 -08001498TEST(STDIO_TEST, fpos_t_and_seek) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001499 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
1500 uselocale(LC_GLOBAL_LOCALE);
1501
Calin Juravle9b95ea92014-05-14 17:07:10 +01001502 // In glibc-2.16 fseek doesn't work properly in wide mode
1503 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is
1504 // to close and re-open the file. We do it in order to make the test pass
1505 // with all glibcs.
1506
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001507 TemporaryFile tf;
1508 FILE* fp = fdopen(tf.fd, "w+");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001509 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001510
1511 wchar_t mb_two_bytes = 0x00a2;
1512 wchar_t mb_three_bytes = 0x20ac;
1513 wchar_t mb_four_bytes = 0x24b62;
1514
1515 // Write to file.
1516 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
1517 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
1518 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
1519
1520 fflush(fp);
1521 fclose(fp);
1522
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08001523 fp = fopen(tf.path, "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001524 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001525
1526 // Store a valid position.
1527 fpos_t mb_two_bytes_pos;
1528 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos));
1529
1530 // Move inside mb_four_bytes with fseek.
1531 long offset_inside_mb = 6;
1532 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET));
1533
1534 // Store the "inside multi byte" position.
1535 fpos_t pos_inside_mb;
1536 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb));
Elliott Hughes063525c2014-05-13 11:19:57 -07001537#if defined(__BIONIC__)
1538 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb));
1539#endif
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001540
1541 // Reading from within a byte should produce an error.
1542 ASSERT_EQ(WEOF, fgetwc(fp));
Elliott Hughes95646e62023-09-21 14:11:19 -07001543 ASSERT_ERRNO(EILSEQ);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001544
1545 // Reverting to a valid position should work.
1546 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos));
1547 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1548
1549 // Moving withing a multi byte with fsetpos should work but reading should
1550 // produce an error.
1551 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb));
1552 ASSERT_EQ(WEOF, fgetwc(fp));
Elliott Hughes95646e62023-09-21 14:11:19 -07001553 ASSERT_ERRNO(EILSEQ);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001554
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001555 ASSERT_EQ(0, fclose(fp));
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001556}
Elliott Hughes6b841db2014-08-20 16:10:49 -07001557
Christopher Ferris13f26a72016-01-13 13:47:58 -08001558TEST(STDIO_TEST, fmemopen) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001559 char buf[16];
1560 memset(buf, 0, sizeof(buf));
1561 FILE* fp = fmemopen(buf, sizeof(buf), "r+");
1562 ASSERT_EQ('<', fputc('<', fp));
1563 ASSERT_NE(EOF, fputs("abc>\n", fp));
1564 fflush(fp);
1565
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001566 // We wrote to the buffer...
Elliott Hughes6b841db2014-08-20 16:10:49 -07001567 ASSERT_STREQ("<abc>\n", buf);
1568
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001569 // And can read back from the file.
Elliott Hughes70715da2016-08-01 16:35:17 -07001570 AssertFileIs(fp, "<abc>\n", true);
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001571 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001572}
1573
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001574TEST(STDIO_TEST, fmemopen_nullptr) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001575 FILE* fp = fmemopen(nullptr, 128, "r+");
1576 ASSERT_NE(EOF, fputs("xyz\n", fp));
1577
Elliott Hughes70715da2016-08-01 16:35:17 -07001578 AssertFileIs(fp, "xyz\n", true);
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001579 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001580}
1581
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001582TEST(STDIO_TEST, fmemopen_trailing_NUL_byte) {
1583 FILE* fp;
1584 char buf[8];
1585
1586 // POSIX: "When a stream open for writing is flushed or closed, a null byte
1587 // shall be written at the current position or at the end of the buffer,
1588 // depending on the size of the contents."
1589 memset(buf, 'x', sizeof(buf));
1590 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w"));
1591 // Even with nothing written (and not in truncate mode), we'll flush a NUL...
1592 ASSERT_EQ(0, fflush(fp));
1593 EXPECT_EQ("\0xxxxxxx"s, std::string(buf, buf + sizeof(buf)));
1594 // Now write and check that the NUL moves along with our writes...
1595 ASSERT_NE(EOF, fputs("hello", fp));
1596 ASSERT_EQ(0, fflush(fp));
1597 EXPECT_EQ("hello\0xx"s, std::string(buf, buf + sizeof(buf)));
1598 ASSERT_NE(EOF, fputs("wo", fp));
1599 ASSERT_EQ(0, fflush(fp));
1600 EXPECT_EQ("hellowo\0"s, std::string(buf, buf + sizeof(buf)));
1601 ASSERT_EQ(0, fclose(fp));
1602
1603 // "If a stream open for update is flushed or closed and the last write has
1604 // advanced the current buffer size, a null byte shall be written at the end
1605 // of the buffer if it fits."
1606 memset(buf, 'x', sizeof(buf));
1607 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r+"));
1608 // Nothing written yet, so no advance...
1609 ASSERT_EQ(0, fflush(fp));
1610 EXPECT_EQ("xxxxxxxx"s, std::string(buf, buf + sizeof(buf)));
1611 ASSERT_NE(EOF, fputs("hello", fp));
1612 ASSERT_EQ(0, fclose(fp));
1613}
1614
1615TEST(STDIO_TEST, fmemopen_size) {
1616 FILE* fp;
Elliott Hughes6b841db2014-08-20 16:10:49 -07001617 char buf[16];
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001618 memset(buf, 'x', sizeof(buf));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001619
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001620 // POSIX: "The stream shall also maintain the size of the current buffer
1621 // contents; use of fseek() or fseeko() on the stream with SEEK_END shall
1622 // seek relative to this size."
Elliott Hughes6b841db2014-08-20 16:10:49 -07001623
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001624 // "For modes r and r+ the size shall be set to the value given by the size
1625 // argument."
1626 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "r"));
1627 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1628 EXPECT_EQ(16, ftell(fp));
1629 EXPECT_EQ(16, ftello(fp));
1630 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1631 EXPECT_EQ(16, ftell(fp));
1632 EXPECT_EQ(16, ftello(fp));
1633 ASSERT_EQ(0, fclose(fp));
1634 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "r+"));
1635 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1636 EXPECT_EQ(16, ftell(fp));
1637 EXPECT_EQ(16, ftello(fp));
1638 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1639 EXPECT_EQ(16, ftell(fp));
1640 EXPECT_EQ(16, ftello(fp));
1641 ASSERT_EQ(0, fclose(fp));
1642
1643 // "For modes w and w+ the initial size shall be zero..."
1644 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w"));
1645 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1646 EXPECT_EQ(0, ftell(fp));
1647 EXPECT_EQ(0, ftello(fp));
1648 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1649 EXPECT_EQ(0, ftell(fp));
1650 EXPECT_EQ(0, ftello(fp));
1651 ASSERT_EQ(0, fclose(fp));
1652 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w+"));
1653 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1654 EXPECT_EQ(0, ftell(fp));
1655 EXPECT_EQ(0, ftello(fp));
1656 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1657 EXPECT_EQ(0, ftell(fp));
1658 EXPECT_EQ(0, ftello(fp));
1659 ASSERT_EQ(0, fclose(fp));
1660
1661 // "...and for modes a and a+ the initial size shall be:
1662 // 1. Zero, if buf is a null pointer
1663 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "a"));
1664 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1665 EXPECT_EQ(0, ftell(fp));
1666 EXPECT_EQ(0, ftello(fp));
1667 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1668 EXPECT_EQ(0, ftell(fp));
1669 EXPECT_EQ(0, ftello(fp));
1670 ASSERT_EQ(0, fclose(fp));
1671 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "a+"));
1672 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1673 EXPECT_EQ(0, ftell(fp));
1674 EXPECT_EQ(0, ftello(fp));
1675 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1676 EXPECT_EQ(0, ftell(fp));
1677 EXPECT_EQ(0, ftello(fp));
1678 ASSERT_EQ(0, fclose(fp));
1679
1680 // 2. The position of the first null byte in the buffer, if one is found
1681 memset(buf, 'x', sizeof(buf));
1682 buf[3] = '\0';
1683 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a"));
1684 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1685 EXPECT_EQ(3, ftell(fp));
1686 EXPECT_EQ(3, ftello(fp));
1687 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1688 EXPECT_EQ(3, ftell(fp));
1689 EXPECT_EQ(3, ftello(fp));
1690 ASSERT_EQ(0, fclose(fp));
1691 memset(buf, 'x', sizeof(buf));
1692 buf[3] = '\0';
1693 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a+"));
1694 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1695 EXPECT_EQ(3, ftell(fp));
1696 EXPECT_EQ(3, ftello(fp));
1697 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1698 EXPECT_EQ(3, ftell(fp));
1699 EXPECT_EQ(3, ftello(fp));
1700 ASSERT_EQ(0, fclose(fp));
1701
1702 // 3. The value of the size argument, if buf is not a null pointer and no
1703 // null byte is found.
1704 memset(buf, 'x', sizeof(buf));
1705 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a"));
1706 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1707 EXPECT_EQ(16, ftell(fp));
1708 EXPECT_EQ(16, ftello(fp));
1709 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1710 EXPECT_EQ(16, ftell(fp));
1711 EXPECT_EQ(16, ftello(fp));
1712 ASSERT_EQ(0, fclose(fp));
1713 memset(buf, 'x', sizeof(buf));
1714 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a+"));
1715 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1716 EXPECT_EQ(16, ftell(fp));
1717 EXPECT_EQ(16, ftello(fp));
1718 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1719 EXPECT_EQ(16, ftell(fp));
1720 EXPECT_EQ(16, ftello(fp));
1721 ASSERT_EQ(0, fclose(fp));
1722}
1723
1724TEST(STDIO_TEST, fmemopen_SEEK_END) {
1725 // fseek SEEK_END is relative to the current string length, not the buffer size.
1726 FILE* fp;
1727 char buf[8];
1728 memset(buf, 'x', sizeof(buf));
1729 strcpy(buf, "str");
1730 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1731 ASSERT_NE(EOF, fputs("string", fp));
1732 EXPECT_EQ(0, fseek(fp, 0, SEEK_END));
1733 EXPECT_EQ(static_cast<long>(strlen("string")), ftell(fp));
1734 EXPECT_EQ(static_cast<off_t>(strlen("string")), ftello(fp));
1735 EXPECT_EQ(0, fclose(fp));
1736
1737 // glibc < 2.22 interpreted SEEK_END the wrong way round (subtracting rather
1738 // than adding).
1739 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1740 ASSERT_NE(EOF, fputs("54321", fp));
1741 EXPECT_EQ(0, fseek(fp, -2, SEEK_END));
1742 EXPECT_EQ('2', fgetc(fp));
1743 EXPECT_EQ(0, fclose(fp));
1744}
1745
1746TEST(STDIO_TEST, fmemopen_seek_invalid) {
1747 char buf[8];
1748 memset(buf, 'x', sizeof(buf));
1749 FILE* fp = fmemopen(buf, sizeof(buf), "w");
1750 ASSERT_TRUE(fp != nullptr);
1751
1752 // POSIX: "An attempt to seek ... to a negative position or to a position
1753 // larger than the buffer size given in the size argument shall fail."
1754 // (There's no mention of what errno should be set to, and glibc doesn't
1755 // set errno in any of these cases.)
1756 EXPECT_EQ(-1, fseek(fp, -2, SEEK_SET));
1757 EXPECT_EQ(-1, fseeko(fp, -2, SEEK_SET));
1758 EXPECT_EQ(-1, fseek(fp, sizeof(buf) + 1, SEEK_SET));
1759 EXPECT_EQ(-1, fseeko(fp, sizeof(buf) + 1, SEEK_SET));
1760}
1761
1762TEST(STDIO_TEST, fmemopen_read_EOF) {
1763 // POSIX: "A read operation on the stream shall not advance the current
1764 // buffer position beyond the current buffer size."
1765 char buf[8];
1766 memset(buf, 'x', sizeof(buf));
1767 FILE* fp = fmemopen(buf, sizeof(buf), "r");
1768 ASSERT_TRUE(fp != nullptr);
1769 char buf2[BUFSIZ];
1770 ASSERT_EQ(8U, fread(buf2, 1, sizeof(buf2), fp));
1771 // POSIX: "Reaching the buffer size in a read operation shall count as
1772 // end-of-file.
1773 ASSERT_TRUE(feof(fp));
1774 ASSERT_EQ(EOF, fgetc(fp));
1775 ASSERT_EQ(0, fclose(fp));
1776}
1777
1778TEST(STDIO_TEST, fmemopen_read_null_bytes) {
1779 // POSIX: "Null bytes in the buffer shall have no special meaning for reads."
1780 char buf[] = "h\0e\0l\0l\0o";
1781 FILE* fp = fmemopen(buf, sizeof(buf), "r");
1782 ASSERT_TRUE(fp != nullptr);
1783 ASSERT_EQ('h', fgetc(fp));
1784 ASSERT_EQ(0, fgetc(fp));
1785 ASSERT_EQ('e', fgetc(fp));
1786 ASSERT_EQ(0, fgetc(fp));
1787 ASSERT_EQ('l', fgetc(fp));
1788 ASSERT_EQ(0, fgetc(fp));
1789 // POSIX: "The read operation shall start at the current buffer position of
1790 // the stream."
1791 char buf2[8];
1792 memset(buf2, 'x', sizeof(buf2));
1793 ASSERT_EQ(4U, fread(buf2, 1, sizeof(buf2), fp));
1794 ASSERT_EQ('l', buf2[0]);
1795 ASSERT_EQ(0, buf2[1]);
1796 ASSERT_EQ('o', buf2[2]);
1797 ASSERT_EQ(0, buf2[3]);
1798 for (size_t i = 4; i < sizeof(buf2); ++i) ASSERT_EQ('x', buf2[i]) << i;
1799 ASSERT_TRUE(feof(fp));
1800 ASSERT_EQ(0, fclose(fp));
1801}
1802
1803TEST(STDIO_TEST, fmemopen_write) {
1804 FILE* fp;
1805 char buf[8];
1806
1807 // POSIX: "A write operation shall start either at the current position of
1808 // the stream (if mode has not specified 'a' as the first character)..."
1809 memset(buf, 'x', sizeof(buf));
1810 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r+"));
1811 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1812 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
1813 ASSERT_EQ(' ', fputc(' ', fp));
1814 EXPECT_EQ("xx xxxxx", std::string(buf, buf + sizeof(buf)));
1815 ASSERT_EQ(0, fclose(fp));
1816
1817 // "...or at the current size of the stream (if mode had 'a' as the first
1818 // character)." (See the fmemopen_size test for what "size" means, but for
1819 // mode "a", it's the first NUL byte.)
1820 memset(buf, 'x', sizeof(buf));
1821 buf[3] = '\0';
1822 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a+"));
1823 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1824 ASSERT_EQ(' ', fputc(' ', fp));
1825 EXPECT_EQ("xxx \0xxx"s, std::string(buf, buf + sizeof(buf)));
1826 ASSERT_EQ(0, fclose(fp));
1827
1828 // "If the current position at the end of the write is larger than the
1829 // current buffer size, the current buffer size shall be set to the current
1830 // position." (See the fmemopen_size test for what "size" means, but to
1831 // query it we SEEK_END with offset 0, and then ftell.)
1832 memset(buf, 'x', sizeof(buf));
1833 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1834 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1835 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1836 EXPECT_EQ(0, ftell(fp));
1837 ASSERT_EQ(' ', fputc(' ', fp));
1838 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1839 EXPECT_EQ(1, ftell(fp));
1840 ASSERT_NE(EOF, fputs("123", fp));
1841 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1842 EXPECT_EQ(4, ftell(fp));
1843 EXPECT_EQ(" 123\0xxx"s, std::string(buf, buf + sizeof(buf)));
1844 ASSERT_EQ(0, fclose(fp));
1845}
1846
1847TEST(STDIO_TEST, fmemopen_write_EOF) {
1848 // POSIX: "A write operation on the stream shall not advance the current
1849 // buffer size beyond the size given in the size argument."
1850 FILE* fp;
1851
1852 // Scalar writes...
1853 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 4, "w"));
1854 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1855 ASSERT_EQ('x', fputc('x', fp));
1856 ASSERT_EQ('x', fputc('x', fp));
1857 ASSERT_EQ('x', fputc('x', fp));
1858 ASSERT_EQ(EOF, fputc('x', fp)); // Only 3 fit because of the implicit NUL.
1859 ASSERT_EQ(0, fclose(fp));
1860
1861 // Vector writes...
1862 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 4, "w"));
1863 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1864 ASSERT_EQ(3U, fwrite("xxxx", 1, 4, fp));
1865 ASSERT_EQ(0, fclose(fp));
1866}
1867
1868TEST(STDIO_TEST, fmemopen_initial_position) {
1869 // POSIX: "The ... current position in the buffer ... shall be initially
1870 // set to either the beginning of the buffer (for r and w modes) ..."
1871 char buf[] = "hello\0world";
1872 FILE* fp;
1873 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r"));
1874 EXPECT_EQ(0L, ftell(fp));
1875 EXPECT_EQ(0, fclose(fp));
1876 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w"));
1877 EXPECT_EQ(0L, ftell(fp));
1878 EXPECT_EQ(0, fclose(fp));
1879 buf[0] = 'h'; // (Undo the effects of the above.)
1880
1881 // POSIX: "...or to the first null byte in the buffer (for a modes)."
1882 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1883 EXPECT_EQ(5L, ftell(fp));
1884 EXPECT_EQ(0, fclose(fp));
1885
1886 // POSIX: "If no null byte is found in append mode, the initial position
1887 // shall be set to one byte after the end of the buffer."
1888 memset(buf, 'x', sizeof(buf));
1889 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1890 EXPECT_EQ(static_cast<long>(sizeof(buf)), ftell(fp));
1891 EXPECT_EQ(0, fclose(fp));
1892}
1893
1894TEST(STDIO_TEST, fmemopen_initial_position_allocated) {
1895 // POSIX: "If buf is a null pointer, the initial position shall always be
1896 // set to the beginning of the buffer."
1897 FILE* fp = fmemopen(nullptr, 128, "a+");
1898 ASSERT_TRUE(fp != nullptr);
1899 EXPECT_EQ(0L, ftell(fp));
1900 EXPECT_EQ(0L, fseek(fp, 0, SEEK_SET));
1901 EXPECT_EQ(0, fclose(fp));
1902}
1903
1904TEST(STDIO_TEST, fmemopen_zero_length) {
1905 // POSIX says it's up to the implementation whether or not you can have a
1906 // zero-length buffer (but "A future version of this standard may require
1907 // support of zero-length buffer streams explicitly"). BSD and glibc < 2.22
1908 // agreed that you couldn't, but glibc >= 2.22 allows it for consistency.
1909 FILE* fp;
1910 char buf[16];
1911 ASSERT_NE(nullptr, fp = fmemopen(buf, 0, "r+"));
1912 ASSERT_EQ(EOF, fgetc(fp));
1913 ASSERT_TRUE(feof(fp));
1914 ASSERT_EQ(0, fclose(fp));
1915 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 0, "r+"));
1916 ASSERT_EQ(EOF, fgetc(fp));
1917 ASSERT_TRUE(feof(fp));
1918 ASSERT_EQ(0, fclose(fp));
1919
1920 ASSERT_NE(nullptr, fp = fmemopen(buf, 0, "w+"));
1921 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1922 ASSERT_EQ(EOF, fputc('x', fp));
1923 ASSERT_EQ(0, fclose(fp));
1924 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 0, "w+"));
1925 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1926 ASSERT_EQ(EOF, fputc('x', fp));
1927 ASSERT_EQ(0, fclose(fp));
1928}
1929
Elliott Hughes288465d2019-02-05 15:00:13 -08001930TEST(STDIO_TEST, fmemopen_zero_length_buffer_overrun) {
1931 char buf[2] = "x";
1932 ASSERT_EQ('x', buf[0]);
1933 FILE* fp = fmemopen(buf, 0, "w");
1934 ASSERT_EQ('x', buf[0]);
1935 ASSERT_EQ(0, fclose(fp));
1936}
1937
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001938TEST(STDIO_TEST, fmemopen_write_only_allocated) {
1939 // POSIX says fmemopen "may fail if the mode argument does not include a '+'".
1940 // BSD fails, glibc doesn't. We side with the more lenient.
1941 FILE* fp;
1942 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "r"));
1943 ASSERT_EQ(0, fclose(fp));
1944 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w"));
1945 ASSERT_EQ(0, fclose(fp));
1946}
1947
1948TEST(STDIO_TEST, fmemopen_fileno) {
1949 // There's no fd backing an fmemopen FILE*.
1950 FILE* fp = fmemopen(nullptr, 16, "r");
1951 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b841db2014-08-20 16:10:49 -07001952 errno = 0;
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001953 ASSERT_EQ(-1, fileno(fp));
Elliott Hughes95646e62023-09-21 14:11:19 -07001954 ASSERT_ERRNO(EBADF);
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001955 ASSERT_EQ(0, fclose(fp));
1956}
1957
1958TEST(STDIO_TEST, fmemopen_append_after_seek) {
1959 // In BSD and glibc < 2.22, append mode didn't force writes to append if
1960 // there had been an intervening seek.
1961
1962 FILE* fp;
1963 char buf[] = "hello\0world";
1964 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1965 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1966 ASSERT_EQ(0, fseek(fp, 0, SEEK_SET));
1967 ASSERT_NE(EOF, fputc('!', fp));
1968 EXPECT_EQ("hello!\0orld\0"s, std::string(buf, buf + sizeof(buf)));
1969 ASSERT_EQ(0, fclose(fp));
1970
1971 memcpy(buf, "hello\0world", sizeof(buf));
1972 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a+"));
1973 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1974 ASSERT_EQ(0, fseek(fp, 0, SEEK_SET));
1975 ASSERT_NE(EOF, fputc('!', fp));
1976 EXPECT_EQ("hello!\0orld\0"s, std::string(buf, buf + sizeof(buf)));
1977 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001978}
1979
Christopher Ferris13f26a72016-01-13 13:47:58 -08001980TEST(STDIO_TEST, open_memstream) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001981 char* p = nullptr;
1982 size_t size = 0;
1983 FILE* fp = open_memstream(&p, &size);
1984 ASSERT_NE(EOF, fputs("hello, world!", fp));
1985 fclose(fp);
1986
1987 ASSERT_STREQ("hello, world!", p);
1988 ASSERT_EQ(strlen("hello, world!"), size);
1989 free(p);
1990}
1991
Christopher Ferris13f26a72016-01-13 13:47:58 -08001992TEST(STDIO_TEST, open_memstream_EINVAL) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001993#if defined(__BIONIC__)
zijunzhao00a3dba2023-03-01 00:07:40 +00001994#pragma clang diagnostic push
1995#pragma clang diagnostic ignored "-Wnonnull"
Elliott Hughes6b841db2014-08-20 16:10:49 -07001996 char* p;
1997 size_t size;
1998
1999 // Invalid buffer.
2000 errno = 0;
2001 ASSERT_EQ(nullptr, open_memstream(nullptr, &size));
Elliott Hughes95646e62023-09-21 14:11:19 -07002002 ASSERT_ERRNO(EINVAL);
Elliott Hughes6b841db2014-08-20 16:10:49 -07002003
2004 // Invalid size.
2005 errno = 0;
2006 ASSERT_EQ(nullptr, open_memstream(&p, nullptr));
Elliott Hughes95646e62023-09-21 14:11:19 -07002007 ASSERT_ERRNO(EINVAL);
zijunzhao00a3dba2023-03-01 00:07:40 +00002008#pragma clang diagnostic pop
Elliott Hughes6b841db2014-08-20 16:10:49 -07002009#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002010 GTEST_SKIP() << "glibc is broken";
Elliott Hughes6b841db2014-08-20 16:10:49 -07002011#endif
2012}
Elliott Hughes31165ed2014-09-23 17:34:29 -07002013
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002014TEST(STDIO_TEST, fdopen_add_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07002015 // This fd doesn't have O_CLOEXEC...
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002016 int fd = open("/proc/version", O_RDONLY);
2017 ASSERT_FALSE(CloseOnExec(fd));
Elliott Hughes31165ed2014-09-23 17:34:29 -07002018 // ...but the new one does.
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002019 FILE* fp = fdopen(fd, "re");
2020 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2021 fclose(fp);
2022}
2023
2024TEST(STDIO_TEST, fdopen_remove_CLOEXEC) {
2025 // This fd has O_CLOEXEC...
2026 int fd = open("/proc/version", O_RDONLY | O_CLOEXEC);
2027 ASSERT_TRUE(CloseOnExec(fd));
2028 // ...but the new one doesn't.
2029 FILE* fp = fdopen(fd, "r");
2030 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2031 fclose(fp);
2032}
2033
2034TEST(STDIO_TEST, freopen_add_CLOEXEC) {
2035 // This FILE* doesn't have O_CLOEXEC...
2036 FILE* fp = fopen("/proc/version", "r");
2037 ASSERT_FALSE(CloseOnExec(fileno(fp)));
2038 // ...but the new one does.
2039 fp = freopen("/proc/version", "re", fp);
2040 ASSERT_TRUE(CloseOnExec(fileno(fp)));
Elliott Hughes31165ed2014-09-23 17:34:29 -07002041
2042 fclose(fp);
Elliott Hughes31165ed2014-09-23 17:34:29 -07002043}
2044
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002045TEST(STDIO_TEST, freopen_remove_CLOEXEC) {
2046 // This FILE* has O_CLOEXEC...
2047 FILE* fp = fopen("/proc/version", "re");
2048 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2049 // ...but the new one doesn't.
2050 fp = freopen("/proc/version", "r", fp);
2051 ASSERT_FALSE(CloseOnExec(fileno(fp)));
2052 fclose(fp);
2053}
Elliott Hughes31165ed2014-09-23 17:34:29 -07002054
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002055TEST(STDIO_TEST, freopen_null_filename_add_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07002056 // This FILE* doesn't have O_CLOEXEC...
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002057 FILE* fp = fopen("/proc/version", "r");
2058 ASSERT_FALSE(CloseOnExec(fileno(fp)));
Elliott Hughes31165ed2014-09-23 17:34:29 -07002059 // ...but the new one does.
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002060 fp = freopen(nullptr, "re", fp);
2061 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2062 fclose(fp);
2063}
Elliott Hughes31165ed2014-09-23 17:34:29 -07002064
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002065TEST(STDIO_TEST, freopen_null_filename_remove_CLOEXEC) {
2066 // This FILE* has O_CLOEXEC...
2067 FILE* fp = fopen("/proc/version", "re");
2068 ASSERT_TRUE(CloseOnExec(fileno(fp)));
2069 // ...but the new one doesn't.
2070 fp = freopen(nullptr, "r", fp);
2071 ASSERT_FALSE(CloseOnExec(fileno(fp)));
Elliott Hughes31165ed2014-09-23 17:34:29 -07002072 fclose(fp);
2073}
Elliott Hughes20841a12014-12-01 16:13:30 -08002074
Elliott Hughesf226ee52016-02-03 11:24:28 -08002075TEST(STDIO_TEST, fopen64_freopen64) {
2076 FILE* fp = fopen64("/proc/version", "r");
2077 ASSERT_TRUE(fp != nullptr);
2078 fp = freopen64("/proc/version", "re", fp);
2079 ASSERT_TRUE(fp != nullptr);
2080 fclose(fp);
2081}
2082
Elliott Hughes20841a12014-12-01 16:13:30 -08002083// https://code.google.com/p/android/issues/detail?id=81155
2084// http://b/18556607
Christopher Ferris13f26a72016-01-13 13:47:58 -08002085TEST(STDIO_TEST, fread_unbuffered_pathological_performance) {
Elliott Hughes20841a12014-12-01 16:13:30 -08002086 FILE* fp = fopen("/dev/zero", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07002087 ASSERT_TRUE(fp != nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08002088
2089 // Make this stream unbuffered.
Yi Kong32bc0fc2018-08-02 17:31:13 -07002090 setvbuf(fp, nullptr, _IONBF, 0);
Elliott Hughes20841a12014-12-01 16:13:30 -08002091
2092 char buf[65*1024];
2093 memset(buf, 0xff, sizeof(buf));
2094
Yi Kong32bc0fc2018-08-02 17:31:13 -07002095 time_t t0 = time(nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08002096 for (size_t i = 0; i < 1024; ++i) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002097 ASSERT_EQ(1U, fread(buf, 64*1024, 1, fp));
Elliott Hughes20841a12014-12-01 16:13:30 -08002098 }
Yi Kong32bc0fc2018-08-02 17:31:13 -07002099 time_t t1 = time(nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08002100
2101 fclose(fp);
2102
2103 // 1024 64KiB reads should have been very quick.
2104 ASSERT_LE(t1 - t0, 1);
2105
2106 for (size_t i = 0; i < 64*1024; ++i) {
2107 ASSERT_EQ('\0', buf[i]);
2108 }
2109 for (size_t i = 64*1024; i < 65*1024; ++i) {
2110 ASSERT_EQ('\xff', buf[i]);
2111 }
2112}
Elliott Hughes75b99382015-01-20 11:23:50 -08002113
Christopher Ferris13f26a72016-01-13 13:47:58 -08002114TEST(STDIO_TEST, fread_EOF) {
Elliott Hughes0ed7e082015-01-22 15:13:38 -08002115 std::string digits("0123456789");
2116 FILE* fp = fmemopen(&digits[0], digits.size(), "r");
Elliott Hughes75b99382015-01-20 11:23:50 -08002117
2118 // Try to read too much, but little enough that it still fits in the FILE's internal buffer.
2119 char buf1[4 * 4];
2120 memset(buf1, 0, sizeof(buf1));
2121 ASSERT_EQ(2U, fread(buf1, 4, 4, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08002122 ASSERT_STREQ("0123456789", buf1);
Elliott Hughes75b99382015-01-20 11:23:50 -08002123 ASSERT_TRUE(feof(fp));
2124
2125 rewind(fp);
2126
Elliott Hughes0ed7e082015-01-22 15:13:38 -08002127 // Try to read way too much so stdio tries to read more direct from the stream.
2128 char buf2[4 * 4096];
Elliott Hughes75b99382015-01-20 11:23:50 -08002129 memset(buf2, 0, sizeof(buf2));
2130 ASSERT_EQ(2U, fread(buf2, 4, 4096, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08002131 ASSERT_STREQ("0123456789", buf2);
Elliott Hughes75b99382015-01-20 11:23:50 -08002132 ASSERT_TRUE(feof(fp));
2133
2134 fclose(fp);
2135}
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002136
2137static void test_fread_from_write_only_stream(size_t n) {
2138 FILE* fp = fopen("/dev/null", "w");
2139 std::vector<char> buf(n, 0);
2140 errno = 0;
2141 ASSERT_EQ(0U, fread(&buf[0], n, 1, fp));
Elliott Hughes95646e62023-09-21 14:11:19 -07002142 ASSERT_ERRNO(EBADF);
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002143 ASSERT_TRUE(ferror(fp));
2144 ASSERT_FALSE(feof(fp));
2145 fclose(fp);
2146}
2147
Christopher Ferris13f26a72016-01-13 13:47:58 -08002148TEST(STDIO_TEST, fread_from_write_only_stream_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002149 test_fread_from_write_only_stream(1);
2150}
2151
Christopher Ferris13f26a72016-01-13 13:47:58 -08002152TEST(STDIO_TEST, fread_from_write_only_stream_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002153 test_fread_from_write_only_stream(64*1024);
2154}
2155
2156static void test_fwrite_after_fread(size_t n) {
2157 TemporaryFile tf;
2158
2159 FILE* fp = fdopen(tf.fd, "w+");
2160 ASSERT_EQ(1U, fwrite("1", 1, 1, fp));
2161 fflush(fp);
2162
2163 // We've flushed but not rewound, so there's nothing to read.
2164 std::vector<char> buf(n, 0);
2165 ASSERT_EQ(0U, fread(&buf[0], 1, buf.size(), fp));
2166 ASSERT_TRUE(feof(fp));
2167
2168 // But hitting EOF doesn't prevent us from writing...
2169 errno = 0;
Elliott Hughes9677fab2016-01-25 15:50:59 -08002170 ASSERT_EQ(1U, fwrite("2", 1, 1, fp)) << strerror(errno);
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002171
2172 // And if we rewind, everything's there.
2173 rewind(fp);
2174 ASSERT_EQ(2U, fread(&buf[0], 1, buf.size(), fp));
2175 ASSERT_EQ('1', buf[0]);
2176 ASSERT_EQ('2', buf[1]);
2177
2178 fclose(fp);
2179}
2180
Christopher Ferris13f26a72016-01-13 13:47:58 -08002181TEST(STDIO_TEST, fwrite_after_fread_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002182 test_fwrite_after_fread(16);
2183}
2184
Christopher Ferris13f26a72016-01-13 13:47:58 -08002185TEST(STDIO_TEST, fwrite_after_fread_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002186 test_fwrite_after_fread(64*1024);
2187}
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002188
2189// http://b/19172514
Christopher Ferris13f26a72016-01-13 13:47:58 -08002190TEST(STDIO_TEST, fread_after_fseek) {
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002191 TemporaryFile tf;
2192
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002193 FILE* fp = fopen(tf.path, "w+");
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002194 ASSERT_TRUE(fp != nullptr);
2195
2196 char file_data[12288];
2197 for (size_t i = 0; i < 12288; i++) {
2198 file_data[i] = i;
2199 }
2200 ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp));
2201 fclose(fp);
2202
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002203 fp = fopen(tf.path, "r");
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002204 ASSERT_TRUE(fp != nullptr);
2205
2206 char buffer[8192];
2207 size_t cur_location = 0;
2208 // Small read to populate internal buffer.
2209 ASSERT_EQ(100U, fread(buffer, 1, 100, fp));
2210 ASSERT_EQ(memcmp(file_data, buffer, 100), 0);
2211
2212 cur_location = static_cast<size_t>(ftell(fp));
2213 // Large read to force reading into the user supplied buffer and bypassing
2214 // the internal buffer.
2215 ASSERT_EQ(8192U, fread(buffer, 1, 8192, fp));
2216 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 8192), 0);
2217
2218 // Small backwards seek to verify fseek does not reuse the internal buffer.
Elliott Hughes9677fab2016-01-25 15:50:59 -08002219 ASSERT_EQ(0, fseek(fp, -22, SEEK_CUR)) << strerror(errno);
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002220 cur_location = static_cast<size_t>(ftell(fp));
2221 ASSERT_EQ(22U, fread(buffer, 1, 22, fp));
2222 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 22), 0);
2223
2224 fclose(fp);
2225}
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002226
2227// https://code.google.com/p/android/issues/detail?id=184847
Christopher Ferris13f26a72016-01-13 13:47:58 -08002228TEST(STDIO_TEST, fread_EOF_184847) {
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002229 TemporaryFile tf;
2230 char buf[6] = {0};
2231
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002232 FILE* fw = fopen(tf.path, "w");
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002233 ASSERT_TRUE(fw != nullptr);
2234
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002235 FILE* fr = fopen(tf.path, "r");
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002236 ASSERT_TRUE(fr != nullptr);
2237
2238 fwrite("a", 1, 1, fw);
2239 fflush(fw);
2240 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
2241 ASSERT_STREQ("a", buf);
2242
2243 // 'fr' is now at EOF.
2244 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
2245 ASSERT_TRUE(feof(fr));
2246
2247 // Write some more...
2248 fwrite("z", 1, 1, fw);
2249 fflush(fw);
2250
2251 // ...and check that we can read it back.
2252 // (BSD thinks that once a stream has hit EOF, it must always return EOF. SysV disagrees.)
2253 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
2254 ASSERT_STREQ("z", buf);
2255
2256 // But now we're done.
2257 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
2258
2259 fclose(fr);
2260 fclose(fw);
2261}
Elliott Hughes923f1652016-01-19 15:46:05 -08002262
2263TEST(STDIO_TEST, fclose_invalidates_fd) {
2264 // The typical error we're trying to help people catch involves accessing
2265 // memory after it's been freed. But we know that stdin/stdout/stderr are
2266 // special and don't get deallocated, so this test uses stdin.
2267 ASSERT_EQ(0, fclose(stdin));
2268
2269 // Even though using a FILE* after close is undefined behavior, I've closed
2270 // this bug as "WAI" too many times. We shouldn't hand out stale fds,
2271 // especially because they might actually correspond to a real stream.
2272 errno = 0;
2273 ASSERT_EQ(-1, fileno(stdin));
Elliott Hughes95646e62023-09-21 14:11:19 -07002274 ASSERT_ERRNO(EBADF);
Elliott Hughes923f1652016-01-19 15:46:05 -08002275}
Elliott Hughes2704bd12016-01-20 17:14:53 -08002276
2277TEST(STDIO_TEST, fseek_ftell_unseekable) {
2278#if defined(__BIONIC__) // glibc has fopencookie instead.
2279 auto read_fn = [](void*, char*, int) { return -1; };
2280 FILE* fp = funopen(nullptr, read_fn, nullptr, nullptr, nullptr);
2281 ASSERT_TRUE(fp != nullptr);
2282
2283 // Check that ftell balks on an unseekable FILE*.
2284 errno = 0;
2285 ASSERT_EQ(-1, ftell(fp));
Elliott Hughes95646e62023-09-21 14:11:19 -07002286 ASSERT_ERRNO(ESPIPE);
Elliott Hughes2704bd12016-01-20 17:14:53 -08002287
2288 // SEEK_CUR is rewritten as SEEK_SET internally...
2289 errno = 0;
2290 ASSERT_EQ(-1, fseek(fp, 0, SEEK_CUR));
Elliott Hughes95646e62023-09-21 14:11:19 -07002291 ASSERT_ERRNO(ESPIPE);
Elliott Hughes2704bd12016-01-20 17:14:53 -08002292
2293 // ...so it's worth testing the direct seek path too.
2294 errno = 0;
2295 ASSERT_EQ(-1, fseek(fp, 0, SEEK_SET));
Elliott Hughes95646e62023-09-21 14:11:19 -07002296 ASSERT_ERRNO(ESPIPE);
Elliott Hughes2704bd12016-01-20 17:14:53 -08002297
2298 fclose(fp);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002299#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002300 GTEST_SKIP() << "glibc uses fopencookie instead";
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002301#endif
2302}
2303
2304TEST(STDIO_TEST, funopen_EINVAL) {
2305#if defined(__BIONIC__)
2306 errno = 0;
2307 ASSERT_EQ(nullptr, funopen(nullptr, nullptr, nullptr, nullptr, nullptr));
Elliott Hughes95646e62023-09-21 14:11:19 -07002308 ASSERT_ERRNO(EINVAL);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002309#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002310 GTEST_SKIP() << "glibc uses fopencookie instead";
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002311#endif
2312}
2313
2314TEST(STDIO_TEST, funopen_seek) {
2315#if defined(__BIONIC__)
2316 auto read_fn = [](void*, char*, int) { return -1; };
2317
2318 auto seek_fn = [](void*, fpos_t, int) -> fpos_t { return 0xfedcba12; };
2319 auto seek64_fn = [](void*, fpos64_t, int) -> fpos64_t { return 0xfedcba12345678; };
2320
2321 FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr);
2322 ASSERT_TRUE(fp != nullptr);
2323 fpos_t pos;
Elliott Hughes955426e2016-01-26 18:25:52 -08002324#if defined(__LP64__)
2325 EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno);
2326 EXPECT_EQ(0xfedcba12LL, pos);
2327#else
2328 EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno);
Elliott Hughes95646e62023-09-21 14:11:19 -07002329 EXPECT_ERRNO(EOVERFLOW);
Elliott Hughes955426e2016-01-26 18:25:52 -08002330#endif
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002331
2332 FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr);
2333 ASSERT_TRUE(fp64 != nullptr);
2334 fpos64_t pos64;
Elliott Hughes955426e2016-01-26 18:25:52 -08002335 EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno);
2336 EXPECT_EQ(0xfedcba12345678, pos64);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002337#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002338 GTEST_SKIP() << "glibc uses fopencookie instead";
Elliott Hughes2704bd12016-01-20 17:14:53 -08002339#endif
2340}
Elliott Hughes71288cb2016-01-22 19:22:44 -08002341
2342TEST(STDIO_TEST, lots_of_concurrent_files) {
2343 std::vector<TemporaryFile*> tfs;
2344 std::vector<FILE*> fps;
2345
2346 for (size_t i = 0; i < 256; ++i) {
2347 TemporaryFile* tf = new TemporaryFile;
2348 tfs.push_back(tf);
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002349 FILE* fp = fopen(tf->path, "w+");
Elliott Hughes71288cb2016-01-22 19:22:44 -08002350 fps.push_back(fp);
2351 fprintf(fp, "hello %zu!\n", i);
2352 fflush(fp);
2353 }
2354
2355 for (size_t i = 0; i < 256; ++i) {
Elliott Hughes71288cb2016-01-22 19:22:44 -08002356 char expected[BUFSIZ];
2357 snprintf(expected, sizeof(expected), "hello %zu!\n", i);
Elliott Hughes71288cb2016-01-22 19:22:44 -08002358
Elliott Hughes70715da2016-08-01 16:35:17 -07002359 AssertFileIs(fps[i], expected);
Elliott Hughes71288cb2016-01-22 19:22:44 -08002360 fclose(fps[i]);
2361 delete tfs[i];
2362 }
2363}
Elliott Hughes9677fab2016-01-25 15:50:59 -08002364
2365static void AssertFileOffsetAt(FILE* fp, off64_t offset) {
2366 EXPECT_EQ(offset, ftell(fp));
2367 EXPECT_EQ(offset, ftello(fp));
Elliott Hughese4fa6e92016-02-02 22:39:15 -08002368 EXPECT_EQ(offset, ftello64(fp));
Elliott Hughes9677fab2016-01-25 15:50:59 -08002369 fpos_t pos;
2370 fpos64_t pos64;
2371 EXPECT_EQ(0, fgetpos(fp, &pos));
2372 EXPECT_EQ(0, fgetpos64(fp, &pos64));
2373#if defined(__BIONIC__)
2374 EXPECT_EQ(offset, static_cast<off64_t>(pos));
2375 EXPECT_EQ(offset, static_cast<off64_t>(pos64));
2376#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08002377 GTEST_SKIP() << "glibc's fpos_t is opaque";
Elliott Hughes9677fab2016-01-25 15:50:59 -08002378#endif
2379}
2380
2381TEST(STDIO_TEST, seek_tell_family_smoke) {
2382 TemporaryFile tf;
2383 FILE* fp = fdopen(tf.fd, "w+");
2384
2385 // Initially we should be at 0.
2386 AssertFileOffsetAt(fp, 0);
2387
2388 // Seek to offset 8192.
2389 ASSERT_EQ(0, fseek(fp, 8192, SEEK_SET));
2390 AssertFileOffsetAt(fp, 8192);
2391 fpos_t eight_k_pos;
2392 ASSERT_EQ(0, fgetpos(fp, &eight_k_pos));
2393
2394 // Seek forward another 8192...
2395 ASSERT_EQ(0, fseek(fp, 8192, SEEK_CUR));
2396 AssertFileOffsetAt(fp, 8192 + 8192);
2397 fpos64_t sixteen_k_pos64;
2398 ASSERT_EQ(0, fgetpos64(fp, &sixteen_k_pos64));
2399
2400 // Seek back 8192...
2401 ASSERT_EQ(0, fseek(fp, -8192, SEEK_CUR));
2402 AssertFileOffsetAt(fp, 8192);
2403
2404 // Since we haven't written anything, the end is also at 0.
2405 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2406 AssertFileOffsetAt(fp, 0);
2407
2408 // Check that our fpos64_t from 16KiB works...
2409 ASSERT_EQ(0, fsetpos64(fp, &sixteen_k_pos64));
2410 AssertFileOffsetAt(fp, 8192 + 8192);
2411 // ...as does our fpos_t from 8192.
2412 ASSERT_EQ(0, fsetpos(fp, &eight_k_pos));
2413 AssertFileOffsetAt(fp, 8192);
2414
2415 // Do fseeko and fseeko64 work too?
2416 ASSERT_EQ(0, fseeko(fp, 1234, SEEK_SET));
2417 AssertFileOffsetAt(fp, 1234);
2418 ASSERT_EQ(0, fseeko64(fp, 5678, SEEK_SET));
2419 AssertFileOffsetAt(fp, 5678);
2420
2421 fclose(fp);
2422}
2423
2424TEST(STDIO_TEST, fseek_fseeko_EINVAL) {
2425 TemporaryFile tf;
2426 FILE* fp = fdopen(tf.fd, "w+");
2427
2428 // Bad whence.
2429 errno = 0;
2430 ASSERT_EQ(-1, fseek(fp, 0, 123));
Elliott Hughes95646e62023-09-21 14:11:19 -07002431 ASSERT_ERRNO(EINVAL);
Elliott Hughes9677fab2016-01-25 15:50:59 -08002432 errno = 0;
2433 ASSERT_EQ(-1, fseeko(fp, 0, 123));
Elliott Hughes95646e62023-09-21 14:11:19 -07002434 ASSERT_ERRNO(EINVAL);
Elliott Hughes9677fab2016-01-25 15:50:59 -08002435 errno = 0;
2436 ASSERT_EQ(-1, fseeko64(fp, 0, 123));
Elliott Hughes95646e62023-09-21 14:11:19 -07002437 ASSERT_ERRNO(EINVAL);
Elliott Hughes9677fab2016-01-25 15:50:59 -08002438
2439 // Bad offset.
2440 errno = 0;
2441 ASSERT_EQ(-1, fseek(fp, -1, SEEK_SET));
Elliott Hughes95646e62023-09-21 14:11:19 -07002442 ASSERT_ERRNO(EINVAL);
Elliott Hughes9677fab2016-01-25 15:50:59 -08002443 errno = 0;
2444 ASSERT_EQ(-1, fseeko(fp, -1, SEEK_SET));
Elliott Hughes95646e62023-09-21 14:11:19 -07002445 ASSERT_ERRNO(EINVAL);
Elliott Hughes9677fab2016-01-25 15:50:59 -08002446 errno = 0;
2447 ASSERT_EQ(-1, fseeko64(fp, -1, SEEK_SET));
Elliott Hughes95646e62023-09-21 14:11:19 -07002448 ASSERT_ERRNO(EINVAL);
Elliott Hughes9677fab2016-01-25 15:50:59 -08002449
2450 fclose(fp);
2451}
Elliott Hughes20788ae2016-06-09 15:16:32 -07002452
2453TEST(STDIO_TEST, ctermid) {
2454 ASSERT_STREQ("/dev/tty", ctermid(nullptr));
2455
2456 char buf[L_ctermid] = {};
2457 ASSERT_EQ(buf, ctermid(buf));
2458 ASSERT_STREQ("/dev/tty", buf);
2459}
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002460
2461TEST(STDIO_TEST, remove) {
2462 struct stat sb;
2463
2464 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002465 ASSERT_EQ(0, remove(tf.path));
2466 ASSERT_EQ(-1, lstat(tf.path, &sb));
Elliott Hughes95646e62023-09-21 14:11:19 -07002467 ASSERT_ERRNO(ENOENT);
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002468
2469 TemporaryDir td;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002470 ASSERT_EQ(0, remove(td.path));
2471 ASSERT_EQ(-1, lstat(td.path, &sb));
Elliott Hughes95646e62023-09-21 14:11:19 -07002472 ASSERT_ERRNO(ENOENT);
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002473
2474 errno = 0;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002475 ASSERT_EQ(-1, remove(tf.path));
Elliott Hughes95646e62023-09-21 14:11:19 -07002476 ASSERT_ERRNO(ENOENT);
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002477
2478 errno = 0;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002479 ASSERT_EQ(-1, remove(td.path));
Elliott Hughes95646e62023-09-21 14:11:19 -07002480 ASSERT_ERRNO(ENOENT);
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002481}
Elliott Hughesfb3873d2016-08-10 11:07:54 -07002482
Elliott Hughese657eb42021-02-18 17:11:56 -08002483TEST_F(STDIO_DEATHTEST, snprintf_30445072_known_buffer_size) {
Elliott Hughesfb3873d2016-08-10 11:07:54 -07002484 char buf[16];
2485 ASSERT_EXIT(snprintf(buf, atol("-1"), "hello"),
2486 testing::KilledBySignal(SIGABRT),
2487#if defined(NOFORTIFY)
2488 "FORTIFY: vsnprintf: size .* > SSIZE_MAX"
2489#else
2490 "FORTIFY: vsnprintf: prevented .*-byte write into 16-byte buffer"
2491#endif
2492 );
2493}
2494
Elliott Hughese657eb42021-02-18 17:11:56 -08002495TEST_F(STDIO_DEATHTEST, snprintf_30445072_unknown_buffer_size) {
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002496 std::string buf = "hello"; // So the compiler doesn't know the buffer size.
Elliott Hughesfb3873d2016-08-10 11:07:54 -07002497 ASSERT_EXIT(snprintf(&buf[0], atol("-1"), "hello"),
2498 testing::KilledBySignal(SIGABRT),
2499 "FORTIFY: vsnprintf: size .* > SSIZE_MAX");
2500}
2501
2502TEST(STDIO_TEST, sprintf_30445072) {
2503 std::string buf = "world";
2504 sprintf(&buf[0], "hello");
2505 ASSERT_EQ(buf, "hello");
2506}
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002507
Elliott Hughes654cd832018-08-30 16:00:42 -07002508TEST(STDIO_TEST, printf_m) {
Elliott Hughes654cd832018-08-30 16:00:42 -07002509 errno = 0;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002510 EXPECT_SNPRINTF("<Success>", "<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002511 errno = -1;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002512 EXPECT_SNPRINTF("<Unknown error -1>", "<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002513 errno = EINVAL;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002514 EXPECT_SNPRINTF("<Invalid argument>", "<%m>");
Elliott Hughesf340a562018-09-06 10:42:40 -07002515}
2516
Elliott Hughes654cd832018-08-30 16:00:42 -07002517TEST(STDIO_TEST, wprintf_m) {
Elliott Hughes654cd832018-08-30 16:00:42 -07002518 errno = 0;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002519 EXPECT_SWPRINTF(L"<Success>", L"<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002520 errno = -1;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002521 EXPECT_SWPRINTF(L"<Unknown error -1>", L"<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002522 errno = EINVAL;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002523 EXPECT_SWPRINTF(L"<Invalid argument>", L"<%m>");
Elliott Hughes654cd832018-08-30 16:00:42 -07002524}
2525
Elliott Hughes2109f122023-09-21 18:32:39 -07002526TEST(STDIO_TEST, printf_hash_m) {
2527 errno = 0;
2528 EXPECT_SNPRINTF("<0>", "<%#m>");
2529 errno = -1;
2530 EXPECT_SNPRINTF("<-1>", "<%#m>");
2531 errno = EINVAL;
2532 EXPECT_SNPRINTF("<EINVAL>", "<%#m>");
2533}
2534
2535TEST(STDIO_TEST, wprintf_hash_m) {
2536 errno = 0;
2537 EXPECT_SWPRINTF(L"<0>", L"<%#m>");
2538 errno = -1;
2539 EXPECT_SWPRINTF(L"<-1>", L"<%#m>");
2540 errno = EINVAL;
2541 EXPECT_SWPRINTF(L"<EINVAL>", L"<%#m>");
2542}
2543
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002544TEST(STDIO_TEST, printf_m_does_not_clobber_strerror) {
Elliott Hughesf340a562018-09-06 10:42:40 -07002545 const char* m = strerror(-1);
2546 ASSERT_STREQ("Unknown error -1", m);
2547 errno = -2;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07002548 EXPECT_SNPRINTF("<Unknown error -2>", "<%m>");
2549 ASSERT_STREQ("Unknown error -1", m);
2550}
2551
2552TEST(STDIO_TEST, wprintf_m_does_not_clobber_strerror) {
2553 const char* m = strerror(-1);
2554 ASSERT_STREQ("Unknown error -1", m);
2555 errno = -2;
2556 EXPECT_SWPRINTF(L"<Unknown error -2>", L"<%m>");
Elliott Hughesf340a562018-09-06 10:42:40 -07002557 ASSERT_STREQ("Unknown error -1", m);
2558}
2559
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002560TEST(STDIO_TEST, fopen_append_mode_and_ftell) {
2561 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002562 SetFileTo(tf.path, "0123456789");
2563 FILE* fp = fopen(tf.path, "a");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002564 EXPECT_EQ(10, ftell(fp));
2565 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2566 EXPECT_EQ(2, ftell(fp));
2567 ASSERT_NE(EOF, fputs("xxx", fp));
2568 ASSERT_EQ(0, fflush(fp));
2569 EXPECT_EQ(13, ftell(fp));
2570 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2571 EXPECT_EQ(13, ftell(fp));
2572 ASSERT_EQ(0, fclose(fp));
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002573 AssertFileIs(tf.path, "0123456789xxx");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002574}
2575
2576TEST(STDIO_TEST, fdopen_append_mode_and_ftell) {
2577 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002578 SetFileTo(tf.path, "0123456789");
2579 int fd = open(tf.path, O_RDWR);
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002580 ASSERT_NE(-1, fd);
2581 // POSIX: "The file position indicator associated with the new stream is set to the position
2582 // indicated by the file offset associated with the file descriptor."
2583 ASSERT_EQ(4, lseek(fd, 4, SEEK_SET));
2584 FILE* fp = fdopen(fd, "a");
2585 EXPECT_EQ(4, ftell(fp));
2586 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2587 EXPECT_EQ(2, ftell(fp));
2588 ASSERT_NE(EOF, fputs("xxx", fp));
2589 ASSERT_EQ(0, fflush(fp));
2590 EXPECT_EQ(13, ftell(fp));
2591 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2592 EXPECT_EQ(13, ftell(fp));
2593 ASSERT_EQ(0, fclose(fp));
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002594 AssertFileIs(tf.path, "0123456789xxx");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002595}
2596
2597TEST(STDIO_TEST, freopen_append_mode_and_ftell) {
2598 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002599 SetFileTo(tf.path, "0123456789");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002600 FILE* other_fp = fopen("/proc/version", "r");
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002601 FILE* fp = freopen(tf.path, "a", other_fp);
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002602 EXPECT_EQ(10, ftell(fp));
2603 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2604 EXPECT_EQ(2, ftell(fp));
2605 ASSERT_NE(EOF, fputs("xxx", fp));
2606 ASSERT_EQ(0, fflush(fp));
2607 EXPECT_EQ(13, ftell(fp));
2608 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2609 EXPECT_EQ(13, ftell(fp));
2610 ASSERT_EQ(0, fclose(fp));
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002611 AssertFileIs(tf.path, "0123456789xxx");
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002612}
Elliott Hughesb15feb72017-07-31 17:20:18 -07002613
2614TEST(STDIO_TEST, constants) {
2615 ASSERT_LE(FILENAME_MAX, PATH_MAX);
2616 ASSERT_EQ(L_tmpnam, PATH_MAX);
2617}
Elliott Hughes37ad9592017-10-30 17:47:12 -07002618
2619TEST(STDIO_TEST, perror) {
2620 ExecTestHelper eth;
Steven Moreland4ef83d62021-10-07 00:19:18 +00002621 eth.Run([&]() { errno = EINVAL; perror("a b c"); exit(0); }, 0, "a b c: Invalid argument\n");
2622 eth.Run([&]() { errno = EINVAL; perror(nullptr); exit(0); }, 0, "Invalid argument\n");
2623 eth.Run([&]() { errno = EINVAL; perror(""); exit(0); }, 0, "Invalid argument\n");
Elliott Hughes37ad9592017-10-30 17:47:12 -07002624}
2625
2626TEST(STDIO_TEST, puts) {
2627 ExecTestHelper eth;
2628 eth.Run([&]() { exit(puts("a b c")); }, 0, "a b c\n");
2629}
2630
Elliott Hughes7cebf832020-08-12 14:25:41 -07002631TEST(STDIO_TEST, putchar) {
2632 ExecTestHelper eth;
2633 eth.Run([&]() { exit(putchar('A')); }, 65, "A");
2634}
2635
2636TEST(STDIO_TEST, putchar_unlocked) {
2637 ExecTestHelper eth;
2638 eth.Run([&]() { exit(putchar('B')); }, 66, "B");
2639}
2640
Elliott Hughes37ad9592017-10-30 17:47:12 -07002641TEST(STDIO_TEST, unlocked) {
2642 TemporaryFile tf;
2643
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002644 FILE* fp = fopen(tf.path, "w+");
Elliott Hughes37ad9592017-10-30 17:47:12 -07002645 ASSERT_TRUE(fp != nullptr);
2646
2647 clearerr_unlocked(fp);
2648 ASSERT_FALSE(feof_unlocked(fp));
2649 ASSERT_FALSE(ferror_unlocked(fp));
2650
2651 ASSERT_EQ(fileno(fp), fileno_unlocked(fp));
2652
2653 ASSERT_NE(EOF, putc_unlocked('a', fp));
2654 ASSERT_NE(EOF, putc('b', fp));
2655 ASSERT_NE(EOF, fputc_unlocked('c', fp));
2656 ASSERT_NE(EOF, fputc('d', fp));
2657
2658 rewind(fp);
2659 ASSERT_EQ('a', getc_unlocked(fp));
2660 ASSERT_EQ('b', getc(fp));
2661 ASSERT_EQ('c', fgetc_unlocked(fp));
2662 ASSERT_EQ('d', fgetc(fp));
2663
2664 rewind(fp);
2665 ASSERT_EQ(2U, fwrite_unlocked("AB", 1, 2, fp));
2666 ASSERT_EQ(2U, fwrite("CD", 1, 2, fp));
2667 ASSERT_EQ(0, fflush_unlocked(fp));
2668
2669 rewind(fp);
2670 char buf[BUFSIZ] = {};
2671 ASSERT_EQ(2U, fread_unlocked(&buf[0], 1, 2, fp));
2672 ASSERT_EQ(2U, fread(&buf[2], 1, 2, fp));
2673 ASSERT_STREQ("ABCD", buf);
2674
2675 rewind(fp);
2676 ASSERT_NE(EOF, fputs("hello ", fp));
2677 ASSERT_NE(EOF, fputs_unlocked("world", fp));
2678 ASSERT_NE(EOF, fputc('\n', fp));
2679
2680 rewind(fp);
2681 ASSERT_TRUE(fgets_unlocked(buf, sizeof(buf), fp) != nullptr);
2682 ASSERT_STREQ("hello world\n", buf);
2683
2684 ASSERT_EQ(0, fclose(fp));
2685}
Ryan Prichardbf549862017-11-07 15:30:32 -08002686
2687TEST(STDIO_TEST, fseek_64bit) {
2688 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002689 FILE* fp = fopen64(tf.path, "w+");
Ryan Prichardbf549862017-11-07 15:30:32 -08002690 ASSERT_TRUE(fp != nullptr);
2691 ASSERT_EQ(0, fseeko64(fp, 0x2'0000'0000, SEEK_SET));
2692 ASSERT_EQ(0x2'0000'0000, ftello64(fp));
2693 ASSERT_EQ(0, fseeko64(fp, 0x1'0000'0000, SEEK_CUR));
2694 ASSERT_EQ(0x3'0000'0000, ftello64(fp));
2695 ASSERT_EQ(0, fclose(fp));
2696}
2697
2698// POSIX requires that fseek/fseeko fail with EOVERFLOW if the new file offset
2699// isn't representable in long/off_t.
2700TEST(STDIO_TEST, fseek_overflow_32bit) {
2701 TemporaryFile tf;
Mark Salyzyn68a3bcc2018-11-13 07:35:21 -08002702 FILE* fp = fopen64(tf.path, "w+");
Ryan Prichardbf549862017-11-07 15:30:32 -08002703 ASSERT_EQ(0, ftruncate64(fileno(fp), 0x2'0000'0000));
2704
2705 // Bionic implements overflow checking for SEEK_CUR, but glibc doesn't.
2706#if defined(__BIONIC__) && !defined(__LP64__)
2707 ASSERT_EQ(0, fseek(fp, 0x7fff'ffff, SEEK_SET));
2708 ASSERT_EQ(-1, fseek(fp, 1, SEEK_CUR));
Elliott Hughes95646e62023-09-21 14:11:19 -07002709 ASSERT_ERRNO(EOVERFLOW);
Ryan Prichardbf549862017-11-07 15:30:32 -08002710#endif
2711
2712 // Neither Bionic nor glibc implement the overflow checking for SEEK_END.
2713 // (Aside: FreeBSD's libc is an example of a libc that checks both SEEK_CUR
2714 // and SEEK_END -- many C libraries check neither.)
2715 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2716 ASSERT_EQ(0x2'0000'0000, ftello64(fp));
2717
2718 fclose(fp);
2719}
Elliott Hughesf1a38382018-08-22 15:38:07 -07002720
2721TEST(STDIO_TEST, dev_std_files) {
2722 // POSIX only mentions /dev/stdout, but we should have all three (http://b/31824379).
2723 char path[PATH_MAX];
Christopher Ferris2c4ec7e2018-08-23 11:17:55 -07002724 ssize_t length = readlink("/dev/stdin", path, sizeof(path));
2725 ASSERT_LT(0, length);
2726 ASSERT_EQ("/proc/self/fd/0", std::string(path, length));
2727
2728 length = readlink("/dev/stdout", path, sizeof(path));
2729 ASSERT_LT(0, length);
2730 ASSERT_EQ("/proc/self/fd/1", std::string(path, length));
2731
2732 length = readlink("/dev/stderr", path, sizeof(path));
2733 ASSERT_LT(0, length);
2734 ASSERT_EQ("/proc/self/fd/2", std::string(path, length));
Elliott Hughesf1a38382018-08-22 15:38:07 -07002735}
Ryan Prichardc485cdb2019-04-30 14:47:34 -07002736
2737TEST(STDIO_TEST, fread_with_locked_file) {
2738 // Reading an unbuffered/line-buffered file from one thread shouldn't block on
2739 // files locked on other threads, even if it flushes some line-buffered files.
2740 FILE* fp1 = fopen("/dev/zero", "r");
2741 ASSERT_TRUE(fp1 != nullptr);
2742 flockfile(fp1);
2743
2744 std::thread([] {
2745 for (int mode : { _IONBF, _IOLBF }) {
2746 FILE* fp2 = fopen("/dev/zero", "r");
2747 ASSERT_TRUE(fp2 != nullptr);
2748 setvbuf(fp2, nullptr, mode, 0);
2749 ASSERT_EQ('\0', fgetc(fp2));
2750 fclose(fp2);
2751 }
2752 }).join();
2753
2754 funlockfile(fp1);
2755 fclose(fp1);
2756}
Elliott Hughes31c73092019-05-07 10:03:02 -07002757
2758TEST(STDIO_TEST, SEEK_macros) {
2759 ASSERT_EQ(0, SEEK_SET);
2760 ASSERT_EQ(1, SEEK_CUR);
2761 ASSERT_EQ(2, SEEK_END);
2762 ASSERT_EQ(3, SEEK_DATA);
2763 ASSERT_EQ(4, SEEK_HOLE);
2764 // So we'll notice if Linux grows another constant in <linux/fs.h>...
2765 ASSERT_EQ(SEEK_MAX, SEEK_HOLE);
2766}
Elliott Hughes05b675e2019-04-17 13:01:06 -07002767
2768TEST(STDIO_TEST, rename) {
2769 TemporaryDir td;
2770 std::string old_path = td.path + "/old"s;
2771 std::string new_path = td.path + "/new"s;
2772
2773 // Create the file, check it exists.
2774 ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
2775 struct stat sb;
2776 ASSERT_EQ(0, stat(old_path.c_str(), &sb));
2777 ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
2778
2779 // Rename and check it moved.
2780 ASSERT_EQ(0, rename(old_path.c_str(), new_path.c_str()));
2781 ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
2782 ASSERT_EQ(0, stat(new_path.c_str(), &sb));
2783}
2784
2785TEST(STDIO_TEST, renameat) {
2786 TemporaryDir td;
2787 android::base::unique_fd dirfd{open(td.path, O_PATH)};
2788 std::string old_path = td.path + "/old"s;
2789 std::string new_path = td.path + "/new"s;
2790
2791 // Create the file, check it exists.
2792 ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
2793 struct stat sb;
2794 ASSERT_EQ(0, stat(old_path.c_str(), &sb));
2795 ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
2796
2797 // Rename and check it moved.
2798 ASSERT_EQ(0, renameat(dirfd, "old", dirfd, "new"));
2799 ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
2800 ASSERT_EQ(0, stat(new_path.c_str(), &sb));
2801}
2802
2803TEST(STDIO_TEST, renameat2) {
Colin Cross4c5595c2021-08-16 15:51:59 -07002804#if defined(__GLIBC__) || defined(ANDROID_HOST_MUSL)
Colin Cross7da20342021-07-28 11:18:11 -07002805 GTEST_SKIP() << "glibc doesn't have renameat2 until 2.28 and musl doesn't have renameat2";
Elliott Hughes05b675e2019-04-17 13:01:06 -07002806#else
2807 TemporaryDir td;
2808 android::base::unique_fd dirfd{open(td.path, O_PATH)};
2809 std::string old_path = td.path + "/old"s;
2810 std::string new_path = td.path + "/new"s;
2811
2812 // Create the file, check it exists.
2813 ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
2814 struct stat sb;
2815 ASSERT_EQ(0, stat(old_path.c_str(), &sb));
2816 ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
2817
2818 // Rename and check it moved.
2819 ASSERT_EQ(0, renameat2(dirfd, "old", dirfd, "new", 0));
2820 ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
2821 ASSERT_EQ(0, stat(new_path.c_str(), &sb));
2822
2823 // After this, both "old" and "new" exist.
2824 ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
2825
2826 // Rename and check it moved.
2827 ASSERT_EQ(-1, renameat2(dirfd, "old", dirfd, "new", RENAME_NOREPLACE));
Elliott Hughes95646e62023-09-21 14:11:19 -07002828 ASSERT_ERRNO(EEXIST);
Elliott Hughes05b675e2019-04-17 13:01:06 -07002829#endif
2830}
2831
2832TEST(STDIO_TEST, renameat2_flags) {
2833#if defined(__GLIBC__)
2834 GTEST_SKIP() << "glibc doesn't have renameat2 until 2.28";
2835#else
2836 ASSERT_NE(0, RENAME_EXCHANGE);
2837 ASSERT_NE(0, RENAME_NOREPLACE);
2838 ASSERT_NE(0, RENAME_WHITEOUT);
2839#endif
2840}
Elliott Hughes7cebf832020-08-12 14:25:41 -07002841
2842TEST(STDIO_TEST, fdopen_failures) {
2843 FILE* fp;
2844 int fd = open("/proc/version", O_RDONLY);
2845 ASSERT_TRUE(fd != -1);
2846
2847 // Nonsense mode.
2848 errno = 0;
2849 fp = fdopen(fd, "nonsense");
2850 ASSERT_TRUE(fp == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -07002851 ASSERT_ERRNO(EINVAL);
Elliott Hughes7cebf832020-08-12 14:25:41 -07002852
2853 // Mode that isn't a subset of the fd's actual mode.
2854 errno = 0;
2855 fp = fdopen(fd, "w");
2856 ASSERT_TRUE(fp == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -07002857 ASSERT_ERRNO(EINVAL);
Elliott Hughes7cebf832020-08-12 14:25:41 -07002858
2859 // Can't set append on the underlying fd.
2860 errno = 0;
2861 fp = fdopen(fd, "a");
2862 ASSERT_TRUE(fp == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -07002863 ASSERT_ERRNO(EINVAL);
Elliott Hughes7cebf832020-08-12 14:25:41 -07002864
2865 // Bad fd.
2866 errno = 0;
2867 fp = fdopen(-1, "re");
2868 ASSERT_TRUE(fp == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -07002869 ASSERT_ERRNO(EBADF);
Elliott Hughes7cebf832020-08-12 14:25:41 -07002870
2871 close(fd);
2872}
2873
2874TEST(STDIO_TEST, fmemopen_invalid_mode) {
2875 errno = 0;
2876 FILE* fp = fmemopen(nullptr, 16, "nonsense");
2877 ASSERT_TRUE(fp == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -07002878 ASSERT_ERRNO(EINVAL);
Elliott Hughes7cebf832020-08-12 14:25:41 -07002879}
2880
2881TEST(STDIO_TEST, fopen_invalid_mode) {
2882 errno = 0;
2883 FILE* fp = fopen("/proc/version", "nonsense");
2884 ASSERT_TRUE(fp == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -07002885 ASSERT_ERRNO(EINVAL);
Elliott Hughes7cebf832020-08-12 14:25:41 -07002886}
2887
2888TEST(STDIO_TEST, freopen_invalid_mode) {
2889 FILE* fp = fopen("/proc/version", "re");
2890 ASSERT_TRUE(fp != nullptr);
2891
2892 errno = 0;
2893 fp = freopen("/proc/version", "nonsense", fp);
2894 ASSERT_TRUE(fp == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -07002895 ASSERT_ERRNO(EINVAL);
Elliott Hughes7cebf832020-08-12 14:25:41 -07002896}
2897
2898TEST(STDIO_TEST, asprintf_smoke) {
2899 char* p = nullptr;
2900 ASSERT_EQ(11, asprintf(&p, "hello %s", "world"));
2901 ASSERT_STREQ("hello world", p);
2902 free(p);
2903}
2904
2905TEST(STDIO_TEST, fopen_ENOENT) {
2906 errno = 0;
2907 FILE* fp = fopen("/proc/does-not-exist", "re");
2908 ASSERT_TRUE(fp == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -07002909 ASSERT_ERRNO(ENOENT);
Elliott Hughes7cebf832020-08-12 14:25:41 -07002910}
Elliott Hughes439ebbd2020-12-04 18:51:42 -08002911
2912static void tempnam_test(bool has_TMPDIR, const char* dir, const char* prefix, const char* re) {
2913 if (has_TMPDIR) {
2914 setenv("TMPDIR", "/my/tmp/dir", 1);
2915 } else {
2916 unsetenv("TMPDIR");
2917 }
2918 char* s1 = tempnam(dir, prefix);
2919 char* s2 = tempnam(dir, prefix);
2920 ASSERT_MATCH(s1, re);
2921 ASSERT_MATCH(s2, re);
2922 ASSERT_STRNE(s1, s2);
2923 free(s1);
2924 free(s2);
2925}
2926
2927TEST(STDIO_TEST, tempnam__system_directory_system_prefix_with_TMPDIR) {
2928 tempnam_test(true, nullptr, nullptr, "^/my/tmp/dir/.*");
2929}
2930
2931TEST(STDIO_TEST, tempnam__system_directory_system_prefix_without_TMPDIR) {
2932 tempnam_test(false, nullptr, nullptr, "^/data/local/tmp/.*");
2933}
2934
2935TEST(STDIO_TEST, tempnam__system_directory_user_prefix_with_TMPDIR) {
2936 tempnam_test(true, nullptr, "prefix", "^/my/tmp/dir/prefix.*");
2937}
2938
2939TEST(STDIO_TEST, tempnam__system_directory_user_prefix_without_TMPDIR) {
2940 tempnam_test(false, nullptr, "prefix", "^/data/local/tmp/prefix.*");
2941}
2942
2943TEST(STDIO_TEST, tempnam__user_directory_system_prefix_with_TMPDIR) {
2944 tempnam_test(true, "/a/b/c", nullptr, "^/my/tmp/dir/.*");
2945}
2946
2947TEST(STDIO_TEST, tempnam__user_directory_system_prefix_without_TMPDIR) {
2948 tempnam_test(false, "/a/b/c", nullptr, "^/a/b/c/.*");
2949}
2950
2951TEST(STDIO_TEST, tempnam__user_directory_user_prefix_with_TMPDIR) {
2952 tempnam_test(true, "/a/b/c", "prefix", "^/my/tmp/dir/prefix.*");
2953}
2954
2955TEST(STDIO_TEST, tempnam__user_directory_user_prefix_without_TMPDIR) {
2956 tempnam_test(false, "/a/b/c", "prefix", "^/a/b/c/prefix.*");
2957}
2958
2959static void tmpnam_test(char* s) {
2960 char s1[L_tmpnam], s2[L_tmpnam];
2961
2962 strcpy(s1, tmpnam(s));
2963 strcpy(s2, tmpnam(s));
2964 ASSERT_MATCH(s1, "/tmp/.*");
2965 ASSERT_MATCH(s2, "/tmp/.*");
2966 ASSERT_STRNE(s1, s2);
2967}
2968
2969TEST(STDIO_TEST, tmpnam) {
2970 tmpnam_test(nullptr);
2971}
2972
2973TEST(STDIO_TEST, tmpnam_buf) {
2974 char buf[L_tmpnam];
2975 tmpnam_test(buf);
2976}
Elliott Hughesf9cfecf2021-02-04 16:58:13 -08002977
2978TEST(STDIO_TEST, freopen_null_filename_mode) {
2979 TemporaryFile tf;
2980 FILE* fp = fopen(tf.path, "r");
2981 ASSERT_TRUE(fp != nullptr);
2982
2983 // "r" = O_RDONLY
2984 char buf[1];
2985 ASSERT_EQ(0, read(fileno(fp), buf, 1));
2986 ASSERT_EQ(-1, write(fileno(fp), "hello", 1));
2987 // "r+" = O_RDWR
2988 fp = freopen(nullptr, "r+", fp);
2989 ASSERT_EQ(0, read(fileno(fp), buf, 1));
2990 ASSERT_EQ(1, write(fileno(fp), "hello", 1));
2991 // "w" = O_WRONLY
2992 fp = freopen(nullptr, "w", fp);
2993 ASSERT_EQ(-1, read(fileno(fp), buf, 1));
2994 ASSERT_EQ(1, write(fileno(fp), "hello", 1));
2995
2996 fclose(fp);
2997}
Elliott Hughesbe78fc92022-07-28 20:58:45 +00002998
Elliott Hughes0cac2912022-08-02 18:25:22 +00002999#if defined(__LP64__)
Elliott Hughesbe78fc92022-07-28 20:58:45 +00003000static int64_t GetTotalRamGiB() {
3001 struct sysinfo si;
3002 sysinfo(&si);
3003 return (static_cast<int64_t>(si.totalram) * si.mem_unit) / 1024 / 1024 / 1024;
3004}
Elliott Hughes0cac2912022-08-02 18:25:22 +00003005#endif
Elliott Hughesbe78fc92022-07-28 20:58:45 +00003006
3007TEST(STDIO_TEST, fread_int_overflow) {
Elliott Hughes0cac2912022-08-02 18:25:22 +00003008#if defined(__LP64__)
Elliott Hughesbe78fc92022-07-28 20:58:45 +00003009 if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
3010
3011 const size_t too_big_for_an_int = 0x80000000ULL;
3012 std::vector<char> buf(too_big_for_an_int);
3013 std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/zero", "re"), fclose};
3014 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 +00003015#else
3016 GTEST_SKIP() << "32-bit can't allocate 2GiB";
3017#endif
Elliott Hughesbe78fc92022-07-28 20:58:45 +00003018}
3019
3020TEST(STDIO_TEST, fwrite_int_overflow) {
Elliott Hughes0cac2912022-08-02 18:25:22 +00003021#if defined(__LP64__)
Elliott Hughesbe78fc92022-07-28 20:58:45 +00003022 if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
3023
3024 const size_t too_big_for_an_int = 0x80000000ULL;
3025 std::vector<char> buf(too_big_for_an_int);
3026 std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/null", "we"), fclose};
3027 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 +00003028#else
3029 GTEST_SKIP() << "32-bit can't allocate 2GiB";
3030#endif
Elliott Hughesbe78fc92022-07-28 20:58:45 +00003031}
Elliott Hughesb813a6a2022-08-01 22:18:40 +00003032
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003033TEST(STDIO_TEST, snprintf_b_B) {
Elliott Hughese50d9d22023-04-19 16:35:40 -07003034#if defined(__BIONIC__)
Elliott Hughese50d9d22023-04-19 16:35:40 -07003035 uint8_t b = 5;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003036 EXPECT_SNPRINTF("<101>", "<%" PRIb8 ">", b);
3037 EXPECT_SNPRINTF("<101>", "<%" PRIB8 ">", b);
3038 EXPECT_SNPRINTF("<00000101>", "<%08" PRIb8 ">", b);
3039 EXPECT_SNPRINTF("<00000101>", "<%08" PRIB8 ">", b);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003040
3041 uint16_t s = 0xaaaa;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003042 EXPECT_SNPRINTF("<1010101010101010>", "<%" PRIb16 ">", s);
3043 EXPECT_SNPRINTF("<1010101010101010>", "<%" PRIB16 ">", s);
3044 EXPECT_SNPRINTF("<0b1010101010101010>", "<%#" PRIb16 ">", s);
3045 EXPECT_SNPRINTF("<0B1010101010101010>", "<%#" PRIB16 ">", s);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003046
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003047 EXPECT_SNPRINTF("<10101010101010101010101010101010>", "<%" PRIb32 ">", 0xaaaaaaaa);
3048 EXPECT_SNPRINTF("<10101010101010101010101010101010>", "<%" PRIB32 ">", 0xaaaaaaaa);
3049 EXPECT_SNPRINTF("<0b10101010101010101010101010101010>", "<%#" PRIb32 ">", 0xaaaaaaaa);
3050 EXPECT_SNPRINTF("<0B10101010101010101010101010101010>", "<%#" PRIB32 ">", 0xaaaaaaaa);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003051
3052 // clang doesn't like "%lb" (https://github.com/llvm/llvm-project/issues/62247)
3053#pragma clang diagnostic push
3054#pragma clang diagnostic ignored "-Wformat"
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003055 EXPECT_SNPRINTF("<1010101010101010101010101010101010101010101010101010101010101010>",
3056 "<%" PRIb64 ">", 0xaaaaaaaa'aaaaaaaa);
3057 EXPECT_SNPRINTF("<1010101010101010101010101010101010101010101010101010101010101010>",
3058 "<%" PRIB64 ">", 0xaaaaaaaa'aaaaaaaa);
3059 EXPECT_SNPRINTF("<0b1010101010101010101010101010101010101010101010101010101010101010>",
3060 "<%#" PRIb64 ">", 0xaaaaaaaa'aaaaaaaa);
3061 EXPECT_SNPRINTF("<0B1010101010101010101010101010101010101010101010101010101010101010>",
3062 "<%#" PRIB64 ">", 0xaaaaaaaa'aaaaaaaa);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003063#pragma clang diagnostic pop
3064
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003065 EXPECT_SNPRINTF("<0>", "<%#b>", 0);
3066 EXPECT_SNPRINTF("<0>", "<%#B>", 0);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003067#else
3068 GTEST_SKIP() << "no %b in glibc";
3069#endif
Elliott Hughesb813a6a2022-08-01 22:18:40 +00003070}
3071
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003072TEST(STDIO_TEST, swprintf_b_B) {
Elliott Hughese50d9d22023-04-19 16:35:40 -07003073#if defined(__BIONIC__)
Elliott Hughese50d9d22023-04-19 16:35:40 -07003074 uint8_t b = 5;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003075 EXPECT_SWPRINTF(L"<101>", L"<%" PRIb8 ">", b);
3076 EXPECT_SWPRINTF(L"<101>", L"<%" PRIB8 ">", b);
3077 EXPECT_SWPRINTF(L"<0b101>", L"<%#" PRIb8 ">", b);
3078 EXPECT_SWPRINTF(L"<0B101>", L"<%#" PRIB8 ">", b);
3079 EXPECT_SWPRINTF(L"<00000101>", L"<%08" PRIb8 ">", b);
3080 EXPECT_SWPRINTF(L"<00000101>", L"<%08" PRIB8 ">", b);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003081
3082 uint16_t s = 0xaaaa;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003083 EXPECT_SWPRINTF(L"<1010101010101010>", L"<%" PRIb16 ">", s);
3084 EXPECT_SWPRINTF(L"<1010101010101010>", L"<%" PRIB16 ">", s);
3085 EXPECT_SWPRINTF(L"<0b1010101010101010>", L"<%#" PRIb16 ">", s);
3086 EXPECT_SWPRINTF(L"<0B1010101010101010>", L"<%#" PRIB16 ">", s);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003087
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003088 EXPECT_SWPRINTF(L"<10101010101010101010101010101010>", L"<%" PRIb32 ">", 0xaaaaaaaa);
3089 EXPECT_SWPRINTF(L"<10101010101010101010101010101010>", L"<%" PRIB32 ">", 0xaaaaaaaa);
3090 EXPECT_SWPRINTF(L"<0b10101010101010101010101010101010>", L"<%#" PRIb32 ">", 0xaaaaaaaa);
3091 EXPECT_SWPRINTF(L"<0B10101010101010101010101010101010>", L"<%#" PRIB32 ">", 0xaaaaaaaa);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003092
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003093 // clang doesn't like "%lb" (https://github.com/llvm/llvm-project/issues/62247)
Elliott Hughese50d9d22023-04-19 16:35:40 -07003094#pragma clang diagnostic push
3095#pragma clang diagnostic ignored "-Wformat"
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003096 EXPECT_SWPRINTF(L"<1010101010101010101010101010101010101010101010101010101010101010>",
3097 L"<%" PRIb64 ">", 0xaaaaaaaa'aaaaaaaa);
3098 EXPECT_SWPRINTF(L"<1010101010101010101010101010101010101010101010101010101010101010>",
3099 L"<%" PRIB64 ">", 0xaaaaaaaa'aaaaaaaa);
3100 EXPECT_SWPRINTF(L"<0b1010101010101010101010101010101010101010101010101010101010101010>",
3101 L"<%#" PRIb64 ">", 0xaaaaaaaa'aaaaaaaa);
3102 EXPECT_SWPRINTF(L"<0B1010101010101010101010101010101010101010101010101010101010101010>",
3103 L"<%#" PRIB64 ">", 0xaaaaaaaa'aaaaaaaa);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003104#pragma clang diagnostic pop
3105
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003106 EXPECT_SWPRINTF(L"<0>", L"<%#b>", 0);
3107 EXPECT_SWPRINTF(L"<0>", L"<%#B>", 0);
Elliott Hughese50d9d22023-04-19 16:35:40 -07003108#else
3109 GTEST_SKIP() << "no %b in glibc";
3110#endif
Elliott Hughesb813a6a2022-08-01 22:18:40 +00003111}
3112
Elliott Hughes1f462de2022-08-05 22:51:05 +00003113TEST(STDIO_TEST, scanf_i_decimal) {
3114 int i;
3115 EXPECT_EQ(1, sscanf("<123789>", "<%i>", &i));
3116 EXPECT_EQ(123789, i);
3117
3118 long long int lli;
3119 char ch;
3120 EXPECT_EQ(2, sscanf("1234567890abcdefg", "%lli%c", &lli, &ch));
3121 EXPECT_EQ(1234567890, lli);
3122 EXPECT_EQ('a', ch);
3123}
3124
3125TEST(STDIO_TEST, scanf_i_hex) {
3126 int i;
3127 EXPECT_EQ(1, sscanf("<0x123abf>", "<%i>", &i));
3128 EXPECT_EQ(0x123abf, i);
3129
3130 long long int lli;
3131 char ch;
3132 EXPECT_EQ(2, sscanf("0x1234567890abcdefg", "%lli%c", &lli, &ch));
3133 EXPECT_EQ(0x1234567890abcdefLL, lli);
3134 EXPECT_EQ('g', ch);
3135}
3136
3137TEST(STDIO_TEST, scanf_i_octal) {
3138 int i;
3139 EXPECT_EQ(1, sscanf("<01234567>", "<%i>", &i));
3140 EXPECT_EQ(01234567, i);
3141
3142 long long int lli;
3143 char ch;
3144 EXPECT_EQ(2, sscanf("010234567890abcdefg", "%lli%c", &lli, &ch));
3145 EXPECT_EQ(010234567, lli);
3146 EXPECT_EQ('8', ch);
3147}
3148
3149TEST(STDIO_TEST, scanf_i_binary) {
3150 int i;
3151 EXPECT_EQ(1, sscanf("<0b101>", "<%i>", &i));
3152 EXPECT_EQ(0b101, i);
3153
3154 long long int lli;
3155 char ch;
3156 EXPECT_EQ(2, sscanf("0b10234567890abcdefg", "%lli%c", &lli, &ch));
3157 EXPECT_EQ(0b10, lli);
3158 EXPECT_EQ('2', ch);
3159}
3160
3161TEST(STDIO_TEST, wscanf_i_decimal) {
3162 int i;
3163 EXPECT_EQ(1, swscanf(L"<123789>", L"<%i>", &i));
3164 EXPECT_EQ(123789, i);
3165
3166 long long int lli;
3167 char ch;
3168 EXPECT_EQ(2, swscanf(L"1234567890abcdefg", L"%lli%c", &lli, &ch));
3169 EXPECT_EQ(1234567890, lli);
3170 EXPECT_EQ('a', ch);
3171}
3172
3173TEST(STDIO_TEST, wscanf_i_hex) {
3174 int i;
3175 EXPECT_EQ(1, swscanf(L"<0x123abf>", L"<%i>", &i));
3176 EXPECT_EQ(0x123abf, i);
3177
3178 long long int lli;
3179 char ch;
3180 EXPECT_EQ(2, swscanf(L"0x1234567890abcdefg", L"%lli%c", &lli, &ch));
3181 EXPECT_EQ(0x1234567890abcdefLL, lli);
3182 EXPECT_EQ('g', ch);
3183}
3184
3185TEST(STDIO_TEST, wscanf_i_octal) {
3186 int i;
3187 EXPECT_EQ(1, swscanf(L"<01234567>", L"<%i>", &i));
3188 EXPECT_EQ(01234567, i);
3189
3190 long long int lli;
3191 char ch;
3192 EXPECT_EQ(2, swscanf(L"010234567890abcdefg", L"%lli%c", &lli, &ch));
3193 EXPECT_EQ(010234567, lli);
3194 EXPECT_EQ('8', ch);
3195}
3196
3197TEST(STDIO_TEST, wscanf_i_binary) {
3198 int i;
3199 EXPECT_EQ(1, swscanf(L"<0b101>", L"<%i>", &i));
3200 EXPECT_EQ(0b101, i);
3201
3202 long long int lli;
3203 char ch;
3204 EXPECT_EQ(2, swscanf(L"0b10234567890abcdefg", L"%lli%c", &lli, &ch));
3205 EXPECT_EQ(0b10, lli);
3206 EXPECT_EQ('2', ch);
3207}
3208
3209TEST(STDIO_TEST, scanf_b) {
Elliott Hughes1f462de2022-08-05 22:51:05 +00003210 int i;
3211 char ch;
3212 EXPECT_EQ(2, sscanf("<1012>", "<%b%c>", &i, &ch));
3213 EXPECT_EQ(0b101, i);
3214 EXPECT_EQ('2', ch);
3215 EXPECT_EQ(1, sscanf("<00000101>", "<%08b>", &i));
3216 EXPECT_EQ(0b00000101, i);
3217 EXPECT_EQ(1, sscanf("<0b1010>", "<%b>", &i));
3218 EXPECT_EQ(0b1010, i);
3219 EXPECT_EQ(2, sscanf("-0b", "%i%c", &i, &ch));
3220 EXPECT_EQ(0, i);
3221 EXPECT_EQ('b', ch);
Elliott Hughes1f462de2022-08-05 22:51:05 +00003222}
3223
3224TEST(STDIO_TEST, swscanf_b) {
Elliott Hughes1f462de2022-08-05 22:51:05 +00003225 int i;
3226 char ch;
3227 EXPECT_EQ(2, swscanf(L"<1012>", L"<%b%c>", &i, &ch));
3228 EXPECT_EQ(0b101, i);
3229 EXPECT_EQ('2', ch);
3230 EXPECT_EQ(1, swscanf(L"<00000101>", L"<%08b>", &i));
3231 EXPECT_EQ(0b00000101, i);
3232 EXPECT_EQ(1, swscanf(L"<0b1010>", L"<%b>", &i));
3233 EXPECT_EQ(0b1010, i);
3234 EXPECT_EQ(2, swscanf(L"-0b", L"%i%c", &i, &ch));
3235 EXPECT_EQ(0, i);
3236 EXPECT_EQ('b', ch);
Elliott Hughes1f462de2022-08-05 22:51:05 +00003237}
zijunzhao3b846ea2023-04-11 20:53:39 +00003238
3239TEST(STDIO_TEST, snprintf_w_base) {
3240#if defined(__BIONIC__)
3241#pragma clang diagnostic push
3242#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3243#pragma clang diagnostic ignored "-Wconstant-conversion"
zijunzhao3b846ea2023-04-11 20:53:39 +00003244 int8_t a = 0b101;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003245 EXPECT_SNPRINTF("<101>", "<%w8b>", a);
zijunzhao3b846ea2023-04-11 20:53:39 +00003246 int8_t b1 = 0xFF;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003247 EXPECT_SNPRINTF("<-1>", "<%w8d>", b1);
zijunzhao3b846ea2023-04-11 20:53:39 +00003248 int8_t b2 = 0x1FF;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003249 EXPECT_SNPRINTF("<-1>", "<%w8d>", b2);
zijunzhao3b846ea2023-04-11 20:53:39 +00003250 int16_t c = 0xFFFF;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003251 EXPECT_SNPRINTF("<-1>", "<%w16i>", c);
zijunzhao3b846ea2023-04-11 20:53:39 +00003252 int32_t d = 021;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003253 EXPECT_SNPRINTF("<21>", "<%w32o>", d);
zijunzhao3b846ea2023-04-11 20:53:39 +00003254 uint32_t e = -1;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003255 EXPECT_SNPRINTF("<4294967295>", "<%w32u>", e);
zijunzhao3b846ea2023-04-11 20:53:39 +00003256 int64_t f = 0x3b;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003257 EXPECT_SNPRINTF("<3b>", "<%w64x>", f);
3258 EXPECT_SNPRINTF("<3B>", "<%w64X>", f);
3259#pragma clang diagnostic pop
3260#else
3261 GTEST_SKIP() << "no %w in glibc";
3262#endif
3263}
3264
3265TEST(STDIO_TEST, swprintf_w_base) {
3266#if defined(__BIONIC__)
3267#pragma clang diagnostic push
3268#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3269#pragma clang diagnostic ignored "-Wconstant-conversion"
3270 int8_t a = 0b101;
3271 EXPECT_SWPRINTF(L"<101>", L"<%w8b>", a);
3272 int8_t b1 = 0xFF;
3273 EXPECT_SWPRINTF(L"<-1>", L"<%w8d>", b1);
3274 int8_t b2 = 0x1FF;
3275 EXPECT_SWPRINTF(L"<-1>", L"<%w8d>", b2);
3276 int16_t c = 0xFFFF;
3277 EXPECT_SWPRINTF(L"<-1>", L"<%w16i>", c);
3278 int32_t d = 021;
3279 EXPECT_SWPRINTF(L"<21>", L"<%w32o>", d);
3280 uint32_t e = -1;
3281 EXPECT_SWPRINTF(L"<4294967295>", L"<%w32u>", e);
3282 int64_t f = 0x3b;
3283 EXPECT_SWPRINTF(L"<3b>", L"<%w64x>", f);
3284 EXPECT_SWPRINTF(L"<3B>", L"<%w64X>", f);
zijunzhao3b846ea2023-04-11 20:53:39 +00003285#pragma clang diagnostic pop
3286#else
3287 GTEST_SKIP() << "no %w in glibc";
3288#endif
3289}
3290
3291TEST(STDIO_TEST, snprintf_w_arguments_reordering) {
3292#if defined(__BIONIC__)
3293#pragma clang diagnostic push
3294#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3295#pragma clang diagnostic ignored "-Wformat-extra-args"
zijunzhao3b846ea2023-04-11 20:53:39 +00003296 int32_t a = 0xaaaaaaaa;
3297 int64_t b = 0x11111111'22222222;
3298 int64_t c = 0x33333333'44444444;
3299 int64_t d = 0xaaaaaaaa'aaaaaaaa;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003300 EXPECT_SNPRINTF("<10101010101010101010101010101010 --- 3333333344444444>",
3301 "<%2$w32b --- %1$w64x>", c, a);
3302 EXPECT_SNPRINTF(
zijunzhao3b846ea2023-04-11 20:53:39 +00003303 "<1010101010101010101010101010101010101010101010101010101010101010 --- 1111111122222222 --- "
3304 "3333333344444444>",
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003305 "<%3$w64b --- %1$w64x --- %2$w64x>", b, c, d);
3306#pragma clang diagnostic pop
3307#else
3308 GTEST_SKIP() << "no %w in glibc";
3309#endif
3310}
3311
3312TEST(STDIO_TEST, swprintf_w_arguments_reordering) {
3313#if defined(__BIONIC__)
3314#pragma clang diagnostic push
3315#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3316#pragma clang diagnostic ignored "-Wformat-extra-args"
3317 int32_t a = 0xaaaaaaaa;
3318 int64_t b = 0x11111111'22222222;
3319 int64_t c = 0x33333333'44444444;
3320 int64_t d = 0xaaaaaaaa'aaaaaaaa;
3321 EXPECT_SWPRINTF(L"<10101010101010101010101010101010 --- 3333333344444444>",
3322 L"<%2$w32b --- %1$w64x>", c, a);
3323 EXPECT_SWPRINTF(
3324 L"<1010101010101010101010101010101010101010101010101010101010101010 --- 1111111122222222 --- "
3325 L"3333333344444444>",
3326 L"<%3$w64b --- %1$w64x --- %2$w64x>", b, c, d);
zijunzhao3b846ea2023-04-11 20:53:39 +00003327#pragma clang diagnostic pop
3328#else
3329 GTEST_SKIP() << "no %w in glibc";
3330#endif
3331}
3332
Christopher Ferrisc833fab2023-07-24 13:55:01 -07003333TEST_F(STDIO_DEATHTEST, snprintf_invalid_w_width) {
zijunzhao3b846ea2023-04-11 20:53:39 +00003334#if defined(__BIONIC__)
3335#pragma clang diagnostic push
3336#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3337 char buf[BUFSIZ];
3338 int32_t a = 100;
3339 EXPECT_DEATH(snprintf(buf, sizeof(buf), "%w20d", &a), "%w20 is unsupported");
3340#pragma clang diagnostic pop
3341#else
3342 GTEST_SKIP() << "no %w in glibc";
3343#endif
3344}
3345
Christopher Ferrisc833fab2023-07-24 13:55:01 -07003346TEST_F(STDIO_DEATHTEST, swprintf_invalid_w_width) {
zijunzhao3b846ea2023-04-11 20:53:39 +00003347#if defined(__BIONIC__)
3348#pragma clang diagnostic push
3349#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3350 wchar_t buf[BUFSIZ];
3351 int32_t a = 100;
3352 EXPECT_DEATH(swprintf(buf, sizeof(buf), L"%w20d", &a), "%w20 is unsupported");
3353#pragma clang diagnostic pop
3354#else
3355 GTEST_SKIP() << "no %w in glibc";
3356#endif
zijunzhao1fdece92023-04-25 17:37:19 +00003357}
3358
3359TEST(STDIO_TEST, snprintf_wf_base) {
3360#if defined(__BIONIC__)
3361#pragma clang diagnostic push
3362#pragma clang diagnostic ignored "-Wconstant-conversion"
3363#pragma clang diagnostic ignored "-Wformat"
3364#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
zijunzhao1fdece92023-04-25 17:37:19 +00003365 int_fast8_t a = 0b101;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003366 EXPECT_SNPRINTF("<101>", "<%wf8b>", a);
zijunzhao1fdece92023-04-25 17:37:19 +00003367 int_fast8_t b = 0x12341234'12341234;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003368 EXPECT_SNPRINTF("<34>", "<%wf8x>", b);
zijunzhao1fdece92023-04-25 17:37:19 +00003369 uint_fast16_t c = 0x11111111'22222222;
3370#if defined(__LP64__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003371 EXPECT_SNPRINTF("<1111111122222222>", "<%wf16x>", c);
zijunzhao1fdece92023-04-25 17:37:19 +00003372#else
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003373 EXPECT_SNPRINTF("<22222222>", "<%wf16x>", c);
zijunzhao1fdece92023-04-25 17:37:19 +00003374#endif
3375 int_fast32_t d = 0x33333333'44444444;
3376#if defined(__LP64__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003377 EXPECT_SNPRINTF("<3333333344444444>", "<%wf32x>", d);
zijunzhao1fdece92023-04-25 17:37:19 +00003378#else
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003379 EXPECT_SNPRINTF("<44444444>", "<%wf32x>", d);
zijunzhao1fdece92023-04-25 17:37:19 +00003380#endif
3381 int_fast64_t e = 0xaaaaaaaa'aaaaaaaa;
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003382 EXPECT_SNPRINTF("<aaaaaaaaaaaaaaaa>", "<%wf64x>", e);
3383 EXPECT_SNPRINTF("<AAAAAAAAAAAAAAAA>", "<%wf64X>", e);
3384#pragma clang diagnostic pop
3385#else
3386 GTEST_SKIP() << "no %wf in glibc";
3387#endif
3388}
3389TEST(STDIO_TEST, swprintf_wf_base) {
3390#if defined(__BIONIC__)
3391#pragma clang diagnostic push
3392#pragma clang diagnostic ignored "-Wconstant-conversion"
3393#pragma clang diagnostic ignored "-Wformat"
3394#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3395 int_fast8_t a = 0b101;
3396 EXPECT_SWPRINTF(L"<101>", L"<%wf8b>", a);
3397 int_fast8_t b = 0x12341234'12341234;
3398 EXPECT_SWPRINTF(L"<34>", L"<%wf8x>", b);
3399 uint_fast16_t c = 0x11111111'22222222;
3400#if defined(__LP64__)
3401 EXPECT_SWPRINTF(L"<1111111122222222>", L"<%wf16x>", c);
3402#else
3403 EXPECT_SWPRINTF(L"<22222222>", L"<%wf16x>", c);
3404#endif
3405 int_fast32_t d = 0x33333333'44444444;
3406#if defined(__LP64__)
3407 EXPECT_SWPRINTF(L"<3333333344444444>", L"<%wf32x>", d);
3408#else
3409 EXPECT_SWPRINTF(L"<44444444>", L"<%wf32x>", d);
3410#endif
3411 int_fast64_t e = 0xaaaaaaaa'aaaaaaaa;
3412 EXPECT_SWPRINTF(L"<aaaaaaaaaaaaaaaa>", L"<%wf64x>", e);
3413 EXPECT_SWPRINTF(L"<AAAAAAAAAAAAAAAA>", L"<%wf64X>", e);
zijunzhao1fdece92023-04-25 17:37:19 +00003414#pragma clang diagnostic pop
3415#else
3416 GTEST_SKIP() << "no %wf in glibc";
3417#endif
3418}
3419
3420TEST(STDIO_TEST, snprintf_wf_arguments_reordering) {
3421#if defined(__BIONIC__)
3422#pragma clang diagnostic push
3423#pragma clang diagnostic ignored "-Wconstant-conversion"
3424#pragma clang diagnostic ignored "-Wformat"
3425#pragma clang diagnostic ignored "-Wformat-extra-args"
3426#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
zijunzhao1fdece92023-04-25 17:37:19 +00003427 int_fast16_t a = 0x11111111'22222222;
3428 int_fast32_t b = 0x33333333'44444444;
3429 int_fast32_t c = 0xaaaaaaaa'aaaaaaaa;
3430#if defined(__LP64__)
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003431 EXPECT_SNPRINTF(
zijunzhao1fdece92023-04-25 17:37:19 +00003432 "<3333333344444444 --- 1010101010101010101010101010101010101010101010101010101010101010>",
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003433 "<%2$wf32x --- %1$wf32b>", c, b);
3434
3435 EXPECT_SNPRINTF(
zijunzhao1fdece92023-04-25 17:37:19 +00003436 "<1010101010101010101010101010101010101010101010101010101010101010 --- 1111111122222222 --- "
3437 "3333333344444444>",
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003438 "<%3$wf32b --- %1$wf16x --- %2$wf32x>", a, b, c);
zijunzhao1fdece92023-04-25 17:37:19 +00003439#else
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003440 EXPECT_SNPRINTF("<44444444 --- 10101010101010101010101010101010>", "<%2$wf32x --- %1$wf32b>", c,
3441 b);
3442 EXPECT_SNPRINTF("<10101010101010101010101010101010 --- 22222222 --- 44444444>",
3443 "<%3$wf32b --- %1$wf16x --- %2$wf32x>", a, b, c);
3444#endif
3445#pragma clang diagnostic pop
3446#else
3447 GTEST_SKIP() << "no %w in glibc";
3448#endif
3449}
3450
3451TEST(STDIO_TEST, swprintf_wf_arguments_reordering) {
3452#if defined(__BIONIC__)
3453#pragma clang diagnostic push
3454#pragma clang diagnostic ignored "-Wconstant-conversion"
3455#pragma clang diagnostic ignored "-Wformat"
3456#pragma clang diagnostic ignored "-Wformat-extra-args"
3457#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3458 int_fast16_t a = 0x11111111'22222222;
3459 int_fast32_t b = 0x33333333'44444444;
3460 int_fast32_t c = 0xaaaaaaaa'aaaaaaaa;
3461#if defined(__LP64__)
3462 EXPECT_SWPRINTF(
3463 L"<3333333344444444 --- 1010101010101010101010101010101010101010101010101010101010101010>",
3464 L"<%2$wf32x --- %1$wf32b>", c, b);
3465
3466 EXPECT_SWPRINTF(
3467 L"<1010101010101010101010101010101010101010101010101010101010101010 --- 1111111122222222 --- "
3468 L"3333333344444444>",
3469 L"<%3$wf32b --- %1$wf16x --- %2$wf32x>", a, b, c);
3470#else
3471 EXPECT_SWPRINTF(L"<44444444 --- 10101010101010101010101010101010>", L"<%2$wf32x --- %1$wf32b>", c,
3472 b);
3473 EXPECT_SWPRINTF(L"<10101010101010101010101010101010 --- 22222222 --- 44444444>",
3474 L"<%3$wf32b --- %1$wf16x --- %2$wf32x>", a, b, c);
zijunzhao1fdece92023-04-25 17:37:19 +00003475#endif
3476#pragma clang diagnostic pop
3477#else
3478 GTEST_SKIP() << "no %w in glibc";
3479#endif
3480}
3481
Christopher Ferrisc833fab2023-07-24 13:55:01 -07003482TEST_F(STDIO_DEATHTEST, snprintf_invalid_wf_width) {
zijunzhao1fdece92023-04-25 17:37:19 +00003483#if defined(__BIONIC__)
3484#pragma clang diagnostic push
3485#pragma clang diagnostic ignored "-Wformat"
3486#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3487 char buf[BUFSIZ];
3488 int_fast32_t a = 100;
3489 EXPECT_DEATH(snprintf(buf, sizeof(buf), "%wf20d", &a), "%wf20 is unsupported");
3490#pragma clang diagnostic pop
3491#else
3492 GTEST_SKIP() << "no %w in glibc";
3493#endif
3494}
3495
Christopher Ferrisc833fab2023-07-24 13:55:01 -07003496TEST_F(STDIO_DEATHTEST, swprintf_invalid_wf_width) {
zijunzhao1fdece92023-04-25 17:37:19 +00003497#if defined(__BIONIC__)
3498#pragma clang diagnostic push
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003499#pragma clang diagnostic ignored "-Wformat"
zijunzhao1fdece92023-04-25 17:37:19 +00003500#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3501 wchar_t buf[BUFSIZ];
3502 int_fast32_t a = 100;
3503 EXPECT_DEATH(swprintf(buf, sizeof(buf), L"%wf20d", &a), "%wf20 is unsupported");
3504#pragma clang diagnostic pop
3505#else
3506 GTEST_SKIP() << "no %w in glibc";
3507#endif
Elliott Hughes8fd4e962023-05-08 17:29:41 -07003508}
zijunzhao78904842023-05-09 00:54:00 +00003509
zijunzhaocc475cf2023-06-13 00:34:13 +00003510TEST(STDIO_TEST, sscanf_w_or_wf_base) {
zijunzhao78904842023-05-09 00:54:00 +00003511#if defined(__BIONIC__)
3512#pragma clang diagnostic push
zijunzhaocc475cf2023-06-13 00:34:13 +00003513#pragma clang diagnostic ignored "-Wformat"
zijunzhao78904842023-05-09 00:54:00 +00003514#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3515 int8_t a;
3516 EXPECT_EQ(1, sscanf("<0b101>", "<%w8b>", &a));
3517 EXPECT_EQ(0b101, a);
zijunzhaocc475cf2023-06-13 00:34:13 +00003518 int_fast8_t fast_a;
3519 EXPECT_EQ(1, sscanf("<0b101>", "<%wf8b>", &fast_a));
3520 EXPECT_EQ(0b101, fast_a);
zijunzhao78904842023-05-09 00:54:00 +00003521 int8_t b1;
3522 EXPECT_EQ(1, sscanf("<0xFF>", "<%w8i>", &b1));
3523 EXPECT_EQ(-1, b1);
3524 int8_t b2;
3525 EXPECT_EQ(1, sscanf("<0x1FF>", "<%w8i>", &b2));
3526 EXPECT_EQ(-1, b2);
zijunzhaocc475cf2023-06-13 00:34:13 +00003527 int_fast8_t fast_b;
3528 EXPECT_EQ(1, sscanf("<0x1234123412341234>", "<%wf8x>", &fast_b));
3529 EXPECT_EQ(0x34, fast_b);
zijunzhao78904842023-05-09 00:54:00 +00003530 int16_t c1;
3531 EXPECT_EQ(1, sscanf("<0xFFFF>", "<%w16i>", &c1));
3532 EXPECT_EQ(-1, c1);
3533 uint16_t c2;
3534 EXPECT_EQ(1, sscanf("<64>", "<%w16d>", &c2));
3535 EXPECT_EQ(64, c2);
zijunzhaocc475cf2023-06-13 00:34:13 +00003536 int_fast16_t fast_c;
3537#if defined(__LP64__)
3538 EXPECT_EQ(1, sscanf("<0x1111111122222222>", "<%wf16x>", &fast_c));
3539 EXPECT_EQ(0x1111111122222222, fast_c);
3540#else
3541 EXPECT_EQ(1, sscanf("<0x1111111122222222>", "<%wf16x>", &fast_c));
3542 EXPECT_EQ(0x22222222, fast_c);
3543#endif
zijunzhao78904842023-05-09 00:54:00 +00003544 int32_t d;
3545 EXPECT_EQ(1, sscanf("<021>", "<%w32o>", &d));
3546 EXPECT_EQ(021, d);
zijunzhaocc475cf2023-06-13 00:34:13 +00003547 int_fast32_t fast_d;
3548#if defined(__LP64__)
3549 EXPECT_EQ(1, sscanf("<0x3333333344444444>", "<%wf32x>", &fast_d));
3550 EXPECT_EQ(0x3333333344444444, fast_d);
3551#else
3552 EXPECT_EQ(1, sscanf("<0x3333333344444444>", "<%wf32x>", &fast_d));
3553 EXPECT_EQ(0x44444444, fast_d);
3554#endif
zijunzhao78904842023-05-09 00:54:00 +00003555 uint32_t e;
3556 EXPECT_EQ(1, sscanf("<-1>", "<%w32u>", &e));
3557 EXPECT_EQ(4294967295, e);
3558 int64_t f;
3559 EXPECT_EQ(1, sscanf("<0x3b>", "<%w64x>", &f));
3560 EXPECT_EQ(0x3b, f);
3561 EXPECT_EQ(1, sscanf("<0x3b>", "<%w64X>", &f));
3562 EXPECT_EQ(0x3B, f);
zijunzhaocc475cf2023-06-13 00:34:13 +00003563 uint_fast64_t fast_f;
3564 EXPECT_EQ(1, sscanf("<0xaaaaaaaa>", "<%wf64x>", &fast_f));
3565 EXPECT_EQ(0xaaaaaaaa, fast_f);
3566 EXPECT_EQ(1, sscanf("<0xaaaaaaaa>", "<%wf64X>", &fast_f));
3567 EXPECT_EQ(0xAAAAAAAA, fast_f);
zijunzhao78904842023-05-09 00:54:00 +00003568#pragma clang diagnostic pop
3569#else
3570 GTEST_SKIP() << "no %w in glibc";
3571#endif
3572}
3573
3574TEST(STDIO_TEST, sscanf_w_combination) {
3575#if defined(__BIONIC__)
3576#pragma clang diagnostic push
3577#pragma clang diagnostic ignored "-Wformat"
3578#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3579#pragma clang diagnostic ignored "-Wformat-extra-args"
3580 uint32_t a;
3581 int64_t b;
3582 char c;
3583
3584 EXPECT_EQ(3, sscanf("<0b10101010101010101010101010101010 0x3333333344444444 1>",
3585 "<%w32b %w64x %c>", &a, &b, &c));
3586 EXPECT_EQ(0xaaaaaaaa, a);
3587 EXPECT_EQ(0x3333333344444444, b);
3588 EXPECT_EQ('1', c);
3589#pragma clang diagnostic pop
3590#else
3591 GTEST_SKIP() << "no %w in glibc";
3592#endif
3593}
3594
Christopher Ferrisc833fab2023-07-24 13:55:01 -07003595TEST_F(STDIO_DEATHTEST, sscanf_invalid_w_or_wf_width) {
zijunzhao78904842023-05-09 00:54:00 +00003596#if defined(__BIONIC__)
3597#pragma clang diagnostic push
zijunzhaocc475cf2023-06-13 00:34:13 +00003598#pragma clang diagnostic ignored "-Wformat"
zijunzhao78904842023-05-09 00:54:00 +00003599#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3600 int32_t a;
3601 EXPECT_DEATH(sscanf("<100>", "<%w20d>", &a), "%w20 is unsupported");
zijunzhaocc475cf2023-06-13 00:34:13 +00003602 int_fast32_t fast_a;
3603 EXPECT_DEATH(sscanf("<100>", "<%wf20d>", &fast_a), "%wf20 is unsupported");
zijunzhao78904842023-05-09 00:54:00 +00003604#pragma clang diagnostic pop
3605#else
3606 GTEST_SKIP() << "no %w in glibc";
3607#endif
3608}
3609
zijunzhaocc475cf2023-06-13 00:34:13 +00003610TEST(STDIO_TEST, swscanf_w_or_wf_base) {
zijunzhao78904842023-05-09 00:54:00 +00003611#if defined(__BIONIC__)
3612#pragma clang diagnostic push
zijunzhaocc475cf2023-06-13 00:34:13 +00003613#pragma clang diagnostic ignored "-Wformat"
zijunzhao78904842023-05-09 00:54:00 +00003614#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3615 int8_t a;
3616 EXPECT_EQ(1, swscanf(L"<0b101>", L"<%w8b>", &a));
3617 EXPECT_EQ(0b101, a);
zijunzhaocc475cf2023-06-13 00:34:13 +00003618 int_fast8_t fast_a;
3619 EXPECT_EQ(1, swscanf(L"<0b101>", L"<%wf8b>", &fast_a));
3620 EXPECT_EQ(0b101, fast_a);
zijunzhao78904842023-05-09 00:54:00 +00003621 int8_t b1;
3622 EXPECT_EQ(1, swscanf(L"<0xFF>", L"<%w8i>", &b1));
3623 EXPECT_EQ(-1, b1);
3624 int8_t b2;
3625 EXPECT_EQ(1, swscanf(L"<0x1FF>", L"<%w8i>", &b2));
3626 EXPECT_EQ(-1, b2);
zijunzhaocc475cf2023-06-13 00:34:13 +00003627 int_fast8_t fast_b;
3628 EXPECT_EQ(1, swscanf(L"<0x1234123412341234>", L"<%wf8i>", &fast_b));
3629 EXPECT_EQ(0x34, fast_b);
zijunzhao78904842023-05-09 00:54:00 +00003630 int16_t c1;
3631 EXPECT_EQ(1, swscanf(L"<0xFFFF>", L"<%w16i>", &c1));
3632 EXPECT_EQ(-1, c1);
3633 uint16_t c2;
3634 EXPECT_EQ(1, swscanf(L"<64>", L"<%w16d>", &c2));
3635 EXPECT_EQ(64, c2);
zijunzhaocc475cf2023-06-13 00:34:13 +00003636 int_fast16_t fast_c;
3637#if defined(__LP64__)
3638 EXPECT_EQ(1, swscanf(L"<0x1111111122222222>", L"<%wf16x>", &fast_c));
3639 EXPECT_EQ(0x1111111122222222, fast_c);
3640#else
3641 EXPECT_EQ(1, swscanf(L"<0x1111111122222222>", L"<%wf16x>", &fast_c));
3642 EXPECT_EQ(0x22222222, fast_c);
3643#endif
zijunzhao78904842023-05-09 00:54:00 +00003644 int32_t d;
3645 EXPECT_EQ(1, swscanf(L"<021>", L"<%w32o>", &d));
3646 EXPECT_EQ(021, d);
zijunzhaocc475cf2023-06-13 00:34:13 +00003647 int_fast32_t fast_d;
3648#if defined(__LP64__)
3649 EXPECT_EQ(1, swscanf(L"<0x3333333344444444>", L"<%wf32x>", &fast_d));
3650 EXPECT_EQ(0x3333333344444444, fast_d);
3651#else
3652 EXPECT_EQ(1, swscanf(L"<0x3333333344444444>", L"<%wf32x>", &fast_d));
3653 EXPECT_EQ(0x44444444, fast_d);
3654#endif
zijunzhao78904842023-05-09 00:54:00 +00003655 uint32_t e;
3656 EXPECT_EQ(1, swscanf(L"<-1>", L"<%w32u>", &e));
3657 EXPECT_EQ(4294967295, e);
3658 int64_t f;
3659 EXPECT_EQ(1, swscanf(L"<0x3b>", L"<%w64x>", &f));
3660 EXPECT_EQ(0x3b, f);
3661 EXPECT_EQ(1, swscanf(L"<0x3b>", L"<%w64X>", &f));
3662 EXPECT_EQ(0x3B, f);
zijunzhaocc475cf2023-06-13 00:34:13 +00003663 uint_fast64_t fast_f;
3664 EXPECT_EQ(1, swscanf(L"<0xaaaaaaaa>", L"<%wf64x>", &fast_f));
3665 EXPECT_EQ(0xaaaaaaaa, fast_f);
3666 EXPECT_EQ(1, swscanf(L"<0xaaaaaaaa>", L"<%wf64X>", &fast_f));
3667 EXPECT_EQ(0xAAAAAAAA, fast_f);
zijunzhao78904842023-05-09 00:54:00 +00003668#pragma clang diagnostic pop
3669#else
3670 GTEST_SKIP() << "no %w in glibc";
3671#endif
3672}
3673
3674TEST(STDIO_TEST, swscanf_w_combination) {
3675#if defined(__BIONIC__)
3676#pragma clang diagnostic push
3677#pragma clang diagnostic ignored "-Wformat"
3678#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3679#pragma clang diagnostic ignored "-Wformat-extra-args"
3680 uint32_t a;
3681 int64_t b;
3682 char c;
3683
3684 EXPECT_EQ(3, swscanf(L"<0b10101010101010101010101010101010 0x3333333344444444 1>",
3685 L"<%w32b %w64x %c>", &a, &b, &c));
3686 EXPECT_EQ(0xaaaaaaaa, a);
3687 EXPECT_EQ(0x3333333344444444, b);
3688 EXPECT_EQ('1', c);
3689#pragma clang diagnostic pop
3690#else
3691 GTEST_SKIP() << "no %w in glibc";
3692#endif
3693}
3694
Christopher Ferrisc833fab2023-07-24 13:55:01 -07003695TEST_F(STDIO_DEATHTEST, swscanf_invalid_w_or_wf_width) {
zijunzhao78904842023-05-09 00:54:00 +00003696#if defined(__BIONIC__)
3697#pragma clang diagnostic push
zijunzhaocc475cf2023-06-13 00:34:13 +00003698#pragma clang diagnostic ignored "-Wformat"
zijunzhao78904842023-05-09 00:54:00 +00003699#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
3700 int32_t a;
3701 EXPECT_DEATH(swscanf(L"<100>", L"<%w20d>", &a), "%w20 is unsupported");
zijunzhaocc475cf2023-06-13 00:34:13 +00003702 int_fast32_t fast_a;
3703 EXPECT_DEATH(swscanf(L"<100>", L"<%wf20d>", &fast_a), "%wf20 is unsupported");
zijunzhao78904842023-05-09 00:54:00 +00003704#pragma clang diagnostic pop
3705#else
3706 GTEST_SKIP() << "no %w in glibc";
3707#endif
Elliott Hughese18c1fa2023-06-26 13:12:57 -07003708}
3709
3710TEST(STDIO_TEST, printf_lc_0) {
3711 // https://austingroupbugs.net/view.php?id=1647
3712 char buf[BUFSIZ];
3713 EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", L'\0'));
3714 EXPECT_TRUE(!memcmp(buf, "<\0>", 3));
3715}