blob: 4107a749030db2c7a77ff420595eb2ad72098ea0 [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>
Elliott Hughes7823f322014-04-14 12:11:28 -070022#include <math.h>
Elliott Hughes91875dc2012-09-24 17:55:15 -070023#include <stdio.h>
24#include <sys/types.h>
Elliott Hughes468efc82018-07-10 14:39:49 -070025#include <sys/socket.h>
Elliott Hughes91875dc2012-09-24 17:55:15 -070026#include <sys/stat.h>
27#include <unistd.h>
Elliott Hughes05493712014-04-17 17:30:03 -070028#include <wchar.h>
Calin Juravle03e4ebe2014-05-08 14:42:06 +010029#include <locale.h>
30
Elliott Hughes3a4c4542017-07-19 17:20:24 -070031#include <string>
Elliott Hughese6bb5a22015-01-23 17:48:15 -080032#include <vector>
33
Elliott Hughesfb3873d2016-08-10 11:07:54 -070034#include "BionicDeathTest.h"
Calin Juravle03e4ebe2014-05-08 14:42:06 +010035#include "TemporaryFile.h"
Josh Gao2f06e102017-01-10 13:00:37 -080036#include "utils.h"
Elliott Hughes91875dc2012-09-24 17:55:15 -070037
Christopher Ferris13f26a72016-01-13 13:47:58 -080038#if defined(NOFORTIFY)
39#define STDIO_TEST stdio_nofortify
Elliott Hughesfb3873d2016-08-10 11:07:54 -070040#define STDIO_DEATHTEST stdio_nofortify_DeathTest
Christopher Ferris13f26a72016-01-13 13:47:58 -080041#else
42#define STDIO_TEST stdio
Elliott Hughesfb3873d2016-08-10 11:07:54 -070043#define STDIO_DEATHTEST stdio_DeathTest
Christopher Ferris13f26a72016-01-13 13:47:58 -080044#endif
45
Elliott Hughes3a4c4542017-07-19 17:20:24 -070046using namespace std::string_literals;
47
Elliott Hughesfb3873d2016-08-10 11:07:54 -070048class stdio_DeathTest : public BionicDeathTest {};
49class stdio_nofortify_DeathTest : public BionicDeathTest {};
50
Elliott Hughes33a8cb12017-07-25 18:06:46 -070051static void SetFileTo(const char* path, const char* content) {
52 FILE* fp;
53 ASSERT_NE(nullptr, fp = fopen(path, "w"));
54 ASSERT_NE(EOF, fputs(content, fp));
55 ASSERT_EQ(0, fclose(fp));
56}
57
58static void AssertFileIs(const char* path, const char* expected) {
59 FILE* fp;
60 ASSERT_NE(nullptr, fp = fopen(path, "r"));
61 char* line = nullptr;
62 size_t length;
63 ASSERT_NE(EOF, getline(&line, &length, fp));
64 ASSERT_EQ(0, fclose(fp));
65 ASSERT_STREQ(expected, line);
66 free(line);
67}
68
Elliott Hughes70715da2016-08-01 16:35:17 -070069static void AssertFileIs(FILE* fp, const char* expected, bool is_fmemopen = false) {
70 rewind(fp);
71
72 char line[1024];
Josh Gao2f06e102017-01-10 13:00:37 -080073 memset(line, 0xff, sizeof(line));
Elliott Hughes70715da2016-08-01 16:35:17 -070074 ASSERT_EQ(line, fgets(line, sizeof(line), fp));
75 ASSERT_STREQ(expected, line);
76
77 if (is_fmemopen) {
78 // fmemopen appends a trailing NUL byte, which probably shouldn't show up as an
79 // extra empty line, but does on every C library I tested...
80 ASSERT_EQ(line, fgets(line, sizeof(line), fp));
81 ASSERT_STREQ("", line);
82 }
83
84 // Make sure there isn't anything else in the file.
85 ASSERT_EQ(nullptr, fgets(line, sizeof(line), fp)) << "junk at end of file: " << line;
86}
87
Christopher Ferris13f26a72016-01-13 13:47:58 -080088TEST(STDIO_TEST, flockfile_18208568_stderr) {
Elliott Hughes6a03abc2014-11-03 12:32:17 -080089 // Check that we have a _recursive_ mutex for flockfile.
90 flockfile(stderr);
91 feof(stderr); // We don't care about the result, but this needs to take the lock.
92 funlockfile(stderr);
93}
94
Christopher Ferris13f26a72016-01-13 13:47:58 -080095TEST(STDIO_TEST, flockfile_18208568_regular) {
Elliott Hughes6a03abc2014-11-03 12:32:17 -080096 // We never had a bug for streams other than stdin/stdout/stderr, but test anyway.
97 FILE* fp = fopen("/dev/null", "w");
Yi Kong32bc0fc2018-08-02 17:31:13 -070098 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6a03abc2014-11-03 12:32:17 -080099 flockfile(fp);
100 feof(fp);
101 funlockfile(fp);
102 fclose(fp);
103}
104
Christopher Ferris13f26a72016-01-13 13:47:58 -0800105TEST(STDIO_TEST, tmpfile_fileno_fprintf_rewind_fgets) {
Elliott Hughes91875dc2012-09-24 17:55:15 -0700106 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700107 ASSERT_TRUE(fp != nullptr);
Elliott Hughes91875dc2012-09-24 17:55:15 -0700108
109 int fd = fileno(fp);
110 ASSERT_NE(fd, -1);
111
112 struct stat sb;
113 int rc = fstat(fd, &sb);
114 ASSERT_NE(rc, -1);
115 ASSERT_EQ(sb.st_mode & 0777, 0600U);
116
117 rc = fprintf(fp, "hello\n");
118 ASSERT_EQ(rc, 6);
119
Elliott Hughes70715da2016-08-01 16:35:17 -0700120 AssertFileIs(fp, "hello\n");
Elliott Hughes91875dc2012-09-24 17:55:15 -0700121 fclose(fp);
122}
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300123
Elliott Hughesf226ee52016-02-03 11:24:28 -0800124TEST(STDIO_TEST, tmpfile64) {
125 FILE* fp = tmpfile64();
126 ASSERT_TRUE(fp != nullptr);
127 fclose(fp);
128}
129
Christopher Ferris13f26a72016-01-13 13:47:58 -0800130TEST(STDIO_TEST, dprintf) {
Calin Juravle6afb2a92014-05-22 11:47:47 +0100131 TemporaryFile tf;
132
133 int rc = dprintf(tf.fd, "hello\n");
134 ASSERT_EQ(rc, 6);
135
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800136 lseek(tf.fd, 0, SEEK_SET);
Christopher Ferris9e01ea62014-05-29 12:49:35 -0700137 FILE* tfile = fdopen(tf.fd, "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700138 ASSERT_TRUE(tfile != nullptr);
Calin Juravle6afb2a92014-05-22 11:47:47 +0100139
Elliott Hughes70715da2016-08-01 16:35:17 -0700140 AssertFileIs(tfile, "hello\n");
Christopher Ferris9e01ea62014-05-29 12:49:35 -0700141 fclose(tfile);
Calin Juravle6afb2a92014-05-22 11:47:47 +0100142}
143
Christopher Ferris13f26a72016-01-13 13:47:58 -0800144TEST(STDIO_TEST, getdelim) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300145 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700146 ASSERT_TRUE(fp != nullptr);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300147
148 const char* line_written = "This is a test";
149 int rc = fprintf(fp, "%s", line_written);
150 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
151
152 rewind(fp);
153
Yi Kong32bc0fc2018-08-02 17:31:13 -0700154 char* word_read = nullptr;
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300155 size_t allocated_length = 0;
156
157 const char* expected[] = { "This ", " ", "is ", "a ", "test" };
158 for (size_t i = 0; i < 5; ++i) {
159 ASSERT_FALSE(feof(fp));
160 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i])));
161 ASSERT_GE(allocated_length, strlen(expected[i]));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800162 ASSERT_STREQ(expected[i], word_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300163 }
164 // The last read should have set the end-of-file indicator for the stream.
165 ASSERT_TRUE(feof(fp));
166 clearerr(fp);
167
168 // getdelim returns -1 but doesn't set errno if we're already at EOF.
169 // It should set the end-of-file indicator for the stream, though.
170 errno = 0;
171 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800172 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300173 ASSERT_TRUE(feof(fp));
174
175 free(word_read);
176 fclose(fp);
177}
178
Christopher Ferris13f26a72016-01-13 13:47:58 -0800179TEST(STDIO_TEST, getdelim_invalid) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300180 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700181 ASSERT_TRUE(fp != nullptr);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300182
Yi Kong32bc0fc2018-08-02 17:31:13 -0700183 char* buffer = nullptr;
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300184 size_t buffer_length = 0;
185
186 // The first argument can't be NULL.
187 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700188 ASSERT_EQ(getdelim(nullptr, &buffer_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800189 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300190
191 // The second argument can't be NULL.
192 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700193 ASSERT_EQ(getdelim(&buffer, nullptr, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800194 ASSERT_EQ(EINVAL, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700195 fclose(fp);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300196}
197
Christopher Ferris13f26a72016-01-13 13:47:58 -0800198TEST(STDIO_TEST, getdelim_directory) {
Elliott Hughes694fd2d2015-04-05 10:51:56 -0700199 FILE* fp = fopen("/proc", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700200 ASSERT_TRUE(fp != nullptr);
Elliott Hughes694fd2d2015-04-05 10:51:56 -0700201 char* word_read;
202 size_t allocated_length;
203 ASSERT_EQ(-1, getdelim(&word_read, &allocated_length, ' ', fp));
204 fclose(fp);
205}
206
Christopher Ferris13f26a72016-01-13 13:47:58 -0800207TEST(STDIO_TEST, getline) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300208 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700209 ASSERT_TRUE(fp != nullptr);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300210
211 const char* line_written = "This is a test for getline\n";
212 const size_t line_count = 5;
213
214 for (size_t i = 0; i < line_count; ++i) {
215 int rc = fprintf(fp, "%s", line_written);
216 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
217 }
218
219 rewind(fp);
220
Yi Kong32bc0fc2018-08-02 17:31:13 -0700221 char* line_read = nullptr;
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300222 size_t allocated_length = 0;
223
224 size_t read_line_count = 0;
225 ssize_t read_char_count;
226 while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) {
227 ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written)));
228 ASSERT_GE(allocated_length, strlen(line_written));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800229 ASSERT_STREQ(line_written, line_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300230 ++read_line_count;
231 }
232 ASSERT_EQ(read_line_count, line_count);
233
234 // The last read should have set the end-of-file indicator for the stream.
235 ASSERT_TRUE(feof(fp));
236 clearerr(fp);
237
238 // getline returns -1 but doesn't set errno if we're already at EOF.
239 // It should set the end-of-file indicator for the stream, though.
240 errno = 0;
241 ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800242 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300243 ASSERT_TRUE(feof(fp));
244
245 free(line_read);
246 fclose(fp);
247}
248
Christopher Ferris13f26a72016-01-13 13:47:58 -0800249TEST(STDIO_TEST, getline_invalid) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300250 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -0700251 ASSERT_TRUE(fp != nullptr);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300252
Yi Kong32bc0fc2018-08-02 17:31:13 -0700253 char* buffer = nullptr;
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300254 size_t buffer_length = 0;
255
256 // The first argument can't be NULL.
257 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700258 ASSERT_EQ(getline(nullptr, &buffer_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800259 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300260
261 // The second argument can't be NULL.
262 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700263 ASSERT_EQ(getline(&buffer, nullptr, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800264 ASSERT_EQ(EINVAL, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700265 fclose(fp);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300266}
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000267
Christopher Ferris13f26a72016-01-13 13:47:58 -0800268TEST(STDIO_TEST, printf_ssize_t) {
Elliott Hughese2556422013-02-28 10:51:14 -0800269 // http://b/8253769
Elliott Hughese2556422013-02-28 10:51:14 -0800270 ASSERT_EQ(sizeof(ssize_t), sizeof(long int));
Elliott Hughesb6e22482013-03-08 15:28:52 -0800271 ASSERT_EQ(sizeof(ssize_t), sizeof(size_t));
272 // For our 32-bit ABI, we had a ssize_t definition that confuses GCC into saying:
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000273 // error: format '%zd' expects argument of type 'signed size_t',
274 // but argument 4 has type 'ssize_t {aka long int}' [-Werror=format]
275 ssize_t v = 1;
276 char buf[32];
277 snprintf(buf, sizeof(buf), "%zd", v);
278}
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800279
Elliott Hughes05493712014-04-17 17:30:03 -0700280// https://code.google.com/p/android/issues/detail?id=64886
Christopher Ferris13f26a72016-01-13 13:47:58 -0800281TEST(STDIO_TEST, snprintf_a) {
Elliott Hughes05493712014-04-17 17:30:03 -0700282 char buf[BUFSIZ];
283 EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235));
284 EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf);
285}
286
Christopher Ferris13f26a72016-01-13 13:47:58 -0800287TEST(STDIO_TEST, snprintf_lc) {
Elliott Hughes05493712014-04-17 17:30:03 -0700288 char buf[BUFSIZ];
289 wint_t wc = L'a';
290 EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc));
291 EXPECT_STREQ("<a>", buf);
292}
293
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700294TEST(STDIO_TEST, snprintf_C) { // Synonym for %lc.
295 char buf[BUFSIZ];
296 wchar_t wc = L'a';
297 EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%C>", wc));
298 EXPECT_STREQ("<a>", buf);
299}
300
Christopher Ferris13f26a72016-01-13 13:47:58 -0800301TEST(STDIO_TEST, snprintf_ls) {
Elliott Hughes05493712014-04-17 17:30:03 -0700302 char buf[BUFSIZ];
Yi Kong32bc0fc2018-08-02 17:31:13 -0700303 wchar_t* ws = nullptr;
Elliott Hughes05493712014-04-17 17:30:03 -0700304 EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws));
305 EXPECT_STREQ("<(null)>", buf);
306
307 wchar_t chars[] = { L'h', L'i', 0 };
308 ws = chars;
309 EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws));
310 EXPECT_STREQ("<hi>", buf);
311}
312
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700313TEST(STDIO_TEST, snprintf_S) { // Synonym for %ls.
314 char buf[BUFSIZ];
Yi Kong32bc0fc2018-08-02 17:31:13 -0700315 wchar_t* ws = nullptr;
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700316 EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%S>", ws));
317 EXPECT_STREQ("<(null)>", buf);
318
319 wchar_t chars[] = { L'h', L'i', 0 };
320 ws = chars;
321 EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%S>", ws));
322 EXPECT_STREQ("<hi>", buf);
323}
324
Christopher Ferris13f26a72016-01-13 13:47:58 -0800325TEST(STDIO_TEST, snprintf_n) {
Elliott Hughes063525c2014-05-13 11:19:57 -0700326#if defined(__BIONIC__)
Elliott Hughes41398d02018-03-07 13:32:58 -0800327 // http://b/14492135 and http://b/31832608.
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700328 char buf[32];
Elliott Hughese2341d02014-05-02 18:16:32 -0700329 int i = 1234;
Elliott Hughes41398d02018-03-07 13:32:58 -0800330 EXPECT_DEATH(snprintf(buf, sizeof(buf), "a %n b", &i), "%n not allowed on Android");
Elliott Hughese2341d02014-05-02 18:16:32 -0700331#else
Elliott Hughes9677fab2016-01-25 15:50:59 -0800332 GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
Elliott Hughese2341d02014-05-02 18:16:32 -0700333#endif
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700334}
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700335
Christopher Ferris13f26a72016-01-13 13:47:58 -0800336TEST(STDIO_TEST, snprintf_smoke) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700337 char buf[BUFSIZ];
338
339 snprintf(buf, sizeof(buf), "a");
340 EXPECT_STREQ("a", buf);
341
342 snprintf(buf, sizeof(buf), "%%");
343 EXPECT_STREQ("%", buf);
344
345 snprintf(buf, sizeof(buf), "01234");
346 EXPECT_STREQ("01234", buf);
347
348 snprintf(buf, sizeof(buf), "a%sb", "01234");
349 EXPECT_STREQ("a01234b", buf);
350
Yi Kong32bc0fc2018-08-02 17:31:13 -0700351 char* s = nullptr;
Elliott Hughes1d13c642013-09-23 16:02:39 -0700352 snprintf(buf, sizeof(buf), "a%sb", s);
353 EXPECT_STREQ("a(null)b", buf);
354
355 snprintf(buf, sizeof(buf), "aa%scc", "bb");
356 EXPECT_STREQ("aabbcc", buf);
357
358 snprintf(buf, sizeof(buf), "a%cc", 'b');
359 EXPECT_STREQ("abc", buf);
360
361 snprintf(buf, sizeof(buf), "a%db", 1234);
362 EXPECT_STREQ("a1234b", buf);
363
364 snprintf(buf, sizeof(buf), "a%db", -8123);
365 EXPECT_STREQ("a-8123b", buf);
366
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700367 snprintf(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010));
Elliott Hughes1d13c642013-09-23 16:02:39 -0700368 EXPECT_STREQ("a16b", buf);
369
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700370 snprintf(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
Elliott Hughes1d13c642013-09-23 16:02:39 -0700371 EXPECT_STREQ("a16b", buf);
372
373 snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
374 EXPECT_STREQ("a68719476736b", buf);
375
376 snprintf(buf, sizeof(buf), "a%ldb", 70000L);
377 EXPECT_STREQ("a70000b", buf);
378
379 snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
380 EXPECT_STREQ("a0xb0001234b", buf);
381
382 snprintf(buf, sizeof(buf), "a%xz", 0x12ab);
383 EXPECT_STREQ("a12abz", buf);
384
385 snprintf(buf, sizeof(buf), "a%Xz", 0x12ab);
386 EXPECT_STREQ("a12ABz", buf);
387
388 snprintf(buf, sizeof(buf), "a%08xz", 0x123456);
389 EXPECT_STREQ("a00123456z", buf);
390
391 snprintf(buf, sizeof(buf), "a%5dz", 1234);
392 EXPECT_STREQ("a 1234z", buf);
393
394 snprintf(buf, sizeof(buf), "a%05dz", 1234);
395 EXPECT_STREQ("a01234z", buf);
396
397 snprintf(buf, sizeof(buf), "a%8dz", 1234);
398 EXPECT_STREQ("a 1234z", buf);
399
400 snprintf(buf, sizeof(buf), "a%-8dz", 1234);
401 EXPECT_STREQ("a1234 z", buf);
402
403 snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef");
404 EXPECT_STREQ("Aabcdef Z", buf);
405
406 snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
407 EXPECT_STREQ("Ahello:1234Z", buf);
408
409 snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
410 EXPECT_STREQ("a005:5:05z", buf);
411
Yi Kong32bc0fc2018-08-02 17:31:13 -0700412 void* p = nullptr;
Elliott Hughes1d13c642013-09-23 16:02:39 -0700413 snprintf(buf, sizeof(buf), "a%d,%pz", 5, p);
Christopher Ferris13613132013-10-28 15:24:04 -0700414#if defined(__BIONIC__)
Elliott Hughes1d13c642013-09-23 16:02:39 -0700415 EXPECT_STREQ("a5,0x0z", buf);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800416#else // __BIONIC__
Christopher Ferris13613132013-10-28 15:24:04 -0700417 EXPECT_STREQ("a5,(nil)z", buf);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800418#endif // __BIONIC__
Elliott Hughes1d13c642013-09-23 16:02:39 -0700419
420 snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
421 EXPECT_STREQ("a68719476736,6,7,8z", buf);
422
423 snprintf(buf, sizeof(buf), "a_%f_b", 1.23f);
424 EXPECT_STREQ("a_1.230000_b", buf);
425
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700426 snprintf(buf, sizeof(buf), "a_%g_b", 3.14);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700427 EXPECT_STREQ("a_3.14_b", buf);
Alexander Ivchenkoedd7c2e2014-04-01 17:01:39 +0400428
429 snprintf(buf, sizeof(buf), "%1$s %1$s", "print_me_twice");
430 EXPECT_STREQ("print_me_twice print_me_twice", buf);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700431}
432
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800433template <typename T>
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700434static void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...),
435 int sscanf_fn(const T*, const T*, ...),
436 const T* fmt_string, const T* fmt, const T* fmt_plus,
437 const T* minus_inf, const T* inf_, const T* plus_inf,
438 const T* minus_nan, const T* nan_, const T* plus_nan) {
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800439 T buf[BUFSIZ];
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700440 float f;
Elliott Hughes7823f322014-04-14 12:11:28 -0700441
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700442 // NaN.
443
444 snprintf_fn(buf, sizeof(buf), fmt, nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800445 EXPECT_STREQ(nan_, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700446 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
447 EXPECT_TRUE(isnan(f));
448
449 snprintf_fn(buf, sizeof(buf), fmt, -nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800450 EXPECT_STREQ(minus_nan, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700451 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
452 EXPECT_TRUE(isnan(f));
453
454 snprintf_fn(buf, sizeof(buf), fmt_plus, nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800455 EXPECT_STREQ(plus_nan, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700456 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
457 EXPECT_TRUE(isnan(f));
458
459 snprintf_fn(buf, sizeof(buf), fmt_plus, -nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800460 EXPECT_STREQ(minus_nan, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700461 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
462 EXPECT_TRUE(isnan(f));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800463
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700464 // Inf.
465
466 snprintf_fn(buf, sizeof(buf), fmt, HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800467 EXPECT_STREQ(inf_, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700468 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
469 EXPECT_EQ(HUGE_VALF, f);
470
471 snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800472 EXPECT_STREQ(minus_inf, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700473 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
474 EXPECT_EQ(-HUGE_VALF, f);
475
476 snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800477 EXPECT_STREQ(plus_inf, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700478 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
479 EXPECT_EQ(HUGE_VALF, f);
480
481 snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800482 EXPECT_STREQ(minus_inf, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700483 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
484 EXPECT_EQ(-HUGE_VALF, f);
485
486 // Check case-insensitivity.
487 snprintf_fn(buf, sizeof(buf), fmt_string, "[InFiNiTy]");
488 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f)) << buf;
489 EXPECT_EQ(HUGE_VALF, f);
490 snprintf_fn(buf, sizeof(buf), fmt_string, "[NaN]");
491 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f)) << buf;
492 EXPECT_TRUE(isnan(f));
Elliott Hughes7823f322014-04-14 12:11:28 -0700493}
494
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700495TEST(STDIO_TEST, snprintf_sscanf_inf_nan) {
496 CheckInfNan(snprintf, sscanf, "%s",
497 "[%a]", "[%+a]",
498 "[-inf]", "[inf]", "[+inf]",
499 "[-nan]", "[nan]", "[+nan]");
500 CheckInfNan(snprintf, sscanf, "%s",
501 "[%A]", "[%+A]",
502 "[-INF]", "[INF]", "[+INF]",
503 "[-NAN]", "[NAN]", "[+NAN]");
504 CheckInfNan(snprintf, sscanf, "%s",
505 "[%e]", "[%+e]",
506 "[-inf]", "[inf]", "[+inf]",
507 "[-nan]", "[nan]", "[+nan]");
508 CheckInfNan(snprintf, sscanf, "%s",
509 "[%E]", "[%+E]",
510 "[-INF]", "[INF]", "[+INF]",
511 "[-NAN]", "[NAN]", "[+NAN]");
512 CheckInfNan(snprintf, sscanf, "%s",
513 "[%f]", "[%+f]",
514 "[-inf]", "[inf]", "[+inf]",
515 "[-nan]", "[nan]", "[+nan]");
516 CheckInfNan(snprintf, sscanf, "%s",
517 "[%F]", "[%+F]",
518 "[-INF]", "[INF]", "[+INF]",
519 "[-NAN]", "[NAN]", "[+NAN]");
520 CheckInfNan(snprintf, sscanf, "%s",
521 "[%g]", "[%+g]",
522 "[-inf]", "[inf]", "[+inf]",
523 "[-nan]", "[nan]", "[+nan]");
524 CheckInfNan(snprintf, sscanf, "%s",
525 "[%G]", "[%+G]",
526 "[-INF]", "[INF]", "[+INF]",
527 "[-NAN]", "[NAN]", "[+NAN]");
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800528}
Elliott Hughes7823f322014-04-14 12:11:28 -0700529
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700530TEST(STDIO_TEST, swprintf_swscanf_inf_nan) {
531 CheckInfNan(swprintf, swscanf, L"%s",
532 L"[%a]", L"[%+a]",
533 L"[-inf]", L"[inf]", L"[+inf]",
534 L"[-nan]", L"[nan]", L"[+nan]");
535 CheckInfNan(swprintf, swscanf, L"%s",
536 L"[%A]", L"[%+A]",
537 L"[-INF]", L"[INF]", L"[+INF]",
538 L"[-NAN]", L"[NAN]", L"[+NAN]");
539 CheckInfNan(swprintf, swscanf, L"%s",
540 L"[%e]", L"[%+e]",
541 L"[-inf]", L"[inf]", L"[+inf]",
542 L"[-nan]", L"[nan]", L"[+nan]");
543 CheckInfNan(swprintf, swscanf, L"%s",
544 L"[%E]", L"[%+E]",
545 L"[-INF]", L"[INF]", L"[+INF]",
546 L"[-NAN]", L"[NAN]", L"[+NAN]");
547 CheckInfNan(swprintf, swscanf, L"%s",
548 L"[%f]", L"[%+f]",
549 L"[-inf]", L"[inf]", L"[+inf]",
550 L"[-nan]", L"[nan]", L"[+nan]");
551 CheckInfNan(swprintf, swscanf, L"%s",
552 L"[%F]", L"[%+F]",
553 L"[-INF]", L"[INF]", L"[+INF]",
554 L"[-NAN]", L"[NAN]", L"[+NAN]");
555 CheckInfNan(swprintf, swscanf, L"%s",
556 L"[%g]", L"[%+g]",
557 L"[-inf]", L"[inf]", L"[+inf]",
558 L"[-nan]", L"[nan]", L"[+nan]");
559 CheckInfNan(swprintf, swscanf, L"%s",
560 L"[%G]", L"[%+G]",
561 L"[-INF]", L"[INF]", L"[+INF]",
562 L"[-NAN]", L"[NAN]", L"[+NAN]");
Elliott Hughes7823f322014-04-14 12:11:28 -0700563}
564
Dan Albert9601f162017-08-09 14:59:06 -0700565TEST(STDIO_TEST, swprintf) {
566 constexpr size_t nchars = 32;
567 wchar_t buf[nchars];
568
569 ASSERT_EQ(2, swprintf(buf, nchars, L"ab")) << strerror(errno);
570 ASSERT_EQ(std::wstring(L"ab"), buf);
571 ASSERT_EQ(5, swprintf(buf, nchars, L"%s", "abcde"));
572 ASSERT_EQ(std::wstring(L"abcde"), buf);
573
574 // Unlike swprintf(), swprintf() returns -1 in case of truncation
575 // and doesn't necessarily zero-terminate the output!
576 ASSERT_EQ(-1, swprintf(buf, 4, L"%s", "abcde"));
577
578 const char kString[] = "Hello, World";
579 ASSERT_EQ(12, swprintf(buf, nchars, L"%s", kString));
580 ASSERT_EQ(std::wstring(L"Hello, World"), buf);
581 ASSERT_EQ(12, swprintf(buf, 13, L"%s", kString));
582 ASSERT_EQ(std::wstring(L"Hello, World"), buf);
583}
584
585TEST(STDIO_TEST, swprintf_a) {
586 constexpr size_t nchars = 32;
587 wchar_t buf[nchars];
588
589 ASSERT_EQ(20, swprintf(buf, nchars, L"%a", 3.1415926535));
590 ASSERT_EQ(std::wstring(L"0x1.921fb54411744p+1"), buf);
591}
592
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700593TEST(STDIO_TEST, swprintf_lc) {
594 constexpr size_t nchars = 32;
595 wchar_t buf[nchars];
596
597 wint_t wc = L'a';
598 EXPECT_EQ(3, swprintf(buf, nchars, L"<%lc>", wc));
599 EXPECT_EQ(std::wstring(L"<a>"), buf);
600}
601
602TEST(STDIO_TEST, swprintf_C) { // Synonym for %lc.
603 constexpr size_t nchars = 32;
604 wchar_t buf[nchars];
605
606 wint_t wc = L'a';
607 EXPECT_EQ(3, swprintf(buf, nchars, L"<%C>", wc));
608 EXPECT_EQ(std::wstring(L"<a>"), buf);
609}
610
Elliott Hughes618303c2017-11-02 16:58:44 -0700611TEST(STDIO_TEST, swprintf_jd_INTMAX_MAX) {
612 constexpr size_t nchars = 32;
613 wchar_t buf[nchars];
614
615 swprintf(buf, nchars, L"%jd", INTMAX_MAX);
616 EXPECT_EQ(std::wstring(L"9223372036854775807"), buf);
617}
618
619TEST(STDIO_TEST, swprintf_jd_INTMAX_MIN) {
620 constexpr size_t nchars = 32;
621 wchar_t buf[nchars];
622
623 swprintf(buf, nchars, L"%jd", INTMAX_MIN);
624 EXPECT_EQ(std::wstring(L"-9223372036854775808"), buf);
625}
626
627TEST(STDIO_TEST, swprintf_ju_UINTMAX_MAX) {
628 constexpr size_t nchars = 32;
629 wchar_t buf[nchars];
630
631 swprintf(buf, nchars, L"%ju", UINTMAX_MAX);
632 EXPECT_EQ(std::wstring(L"18446744073709551615"), buf);
633}
634
635TEST(STDIO_TEST, swprintf_1$ju_UINTMAX_MAX) {
636 constexpr size_t nchars = 32;
637 wchar_t buf[nchars];
638
639 swprintf(buf, nchars, L"%1$ju", UINTMAX_MAX);
640 EXPECT_EQ(std::wstring(L"18446744073709551615"), buf);
641}
642
Dan Albert9601f162017-08-09 14:59:06 -0700643TEST(STDIO_TEST, swprintf_ls) {
644 constexpr size_t nchars = 32;
645 wchar_t buf[nchars];
646
647 static const wchar_t kWideString[] = L"Hello\uff41 World";
648 ASSERT_EQ(12, swprintf(buf, nchars, L"%ls", kWideString));
649 ASSERT_EQ(std::wstring(kWideString), buf);
650 ASSERT_EQ(12, swprintf(buf, 13, L"%ls", kWideString));
651 ASSERT_EQ(std::wstring(kWideString), buf);
652}
653
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700654TEST(STDIO_TEST, swprintf_S) { // Synonym for %ls.
655 constexpr size_t nchars = 32;
656 wchar_t buf[nchars];
657
658 static const wchar_t kWideString[] = L"Hello\uff41 World";
659 ASSERT_EQ(12, swprintf(buf, nchars, L"%S", kWideString));
660 ASSERT_EQ(std::wstring(kWideString), buf);
661 ASSERT_EQ(12, swprintf(buf, 13, L"%S", kWideString));
662 ASSERT_EQ(std::wstring(kWideString), buf);
663}
664
Christopher Ferris13f26a72016-01-13 13:47:58 -0800665TEST(STDIO_TEST, snprintf_d_INT_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700666 char buf[BUFSIZ];
667 snprintf(buf, sizeof(buf), "%d", INT_MAX);
668 EXPECT_STREQ("2147483647", buf);
669}
670
Christopher Ferris13f26a72016-01-13 13:47:58 -0800671TEST(STDIO_TEST, snprintf_d_INT_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700672 char buf[BUFSIZ];
673 snprintf(buf, sizeof(buf), "%d", INT_MIN);
674 EXPECT_STREQ("-2147483648", buf);
675}
676
Elliott Hughes618303c2017-11-02 16:58:44 -0700677TEST(STDIO_TEST, snprintf_jd_INTMAX_MAX) {
678 char buf[BUFSIZ];
679 snprintf(buf, sizeof(buf), "%jd", INTMAX_MAX);
680 EXPECT_STREQ("9223372036854775807", buf);
681}
682
683TEST(STDIO_TEST, snprintf_jd_INTMAX_MIN) {
684 char buf[BUFSIZ];
685 snprintf(buf, sizeof(buf), "%jd", INTMAX_MIN);
686 EXPECT_STREQ("-9223372036854775808", buf);
687}
688
689TEST(STDIO_TEST, snprintf_ju_UINTMAX_MAX) {
690 char buf[BUFSIZ];
691 snprintf(buf, sizeof(buf), "%ju", UINTMAX_MAX);
692 EXPECT_STREQ("18446744073709551615", buf);
693}
694
695TEST(STDIO_TEST, snprintf_1$ju_UINTMAX_MAX) {
696 char buf[BUFSIZ];
697 snprintf(buf, sizeof(buf), "%1$ju", UINTMAX_MAX);
698 EXPECT_STREQ("18446744073709551615", buf);
699}
700
Christopher Ferris13f26a72016-01-13 13:47:58 -0800701TEST(STDIO_TEST, snprintf_ld_LONG_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700702 char buf[BUFSIZ];
703 snprintf(buf, sizeof(buf), "%ld", LONG_MAX);
Josh Gaob36efa42016-09-15 13:55:41 -0700704#if defined(__LP64__)
Elliott Hughes925753a2013-10-18 13:17:18 -0700705 EXPECT_STREQ("9223372036854775807", buf);
706#else
Elliott Hughes1d13c642013-09-23 16:02:39 -0700707 EXPECT_STREQ("2147483647", buf);
Elliott Hughes925753a2013-10-18 13:17:18 -0700708#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700709}
710
Christopher Ferris13f26a72016-01-13 13:47:58 -0800711TEST(STDIO_TEST, snprintf_ld_LONG_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700712 char buf[BUFSIZ];
713 snprintf(buf, sizeof(buf), "%ld", LONG_MIN);
Josh Gaob36efa42016-09-15 13:55:41 -0700714#if defined(__LP64__)
Elliott Hughes925753a2013-10-18 13:17:18 -0700715 EXPECT_STREQ("-9223372036854775808", buf);
716#else
Elliott Hughes1d13c642013-09-23 16:02:39 -0700717 EXPECT_STREQ("-2147483648", buf);
Elliott Hughes925753a2013-10-18 13:17:18 -0700718#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700719}
720
Christopher Ferris13f26a72016-01-13 13:47:58 -0800721TEST(STDIO_TEST, snprintf_lld_LLONG_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700722 char buf[BUFSIZ];
723 snprintf(buf, sizeof(buf), "%lld", LLONG_MAX);
724 EXPECT_STREQ("9223372036854775807", buf);
725}
726
Christopher Ferris13f26a72016-01-13 13:47:58 -0800727TEST(STDIO_TEST, snprintf_lld_LLONG_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700728 char buf[BUFSIZ];
729 snprintf(buf, sizeof(buf), "%lld", LLONG_MIN);
730 EXPECT_STREQ("-9223372036854775808", buf);
731}
732
Elliott Hughes2f9c8ce2017-11-01 13:54:47 -0700733TEST(STDIO_TEST, snprintf_o_UINT_MAX) {
734 char buf[BUFSIZ];
735 snprintf(buf, sizeof(buf), "%o", UINT_MAX);
736 EXPECT_STREQ("37777777777", buf);
737}
738
739TEST(STDIO_TEST, snprintf_u_UINT_MAX) {
740 char buf[BUFSIZ];
741 snprintf(buf, sizeof(buf), "%u", UINT_MAX);
742 EXPECT_STREQ("4294967295", buf);
743}
744
745TEST(STDIO_TEST, snprintf_x_UINT_MAX) {
746 char buf[BUFSIZ];
747 snprintf(buf, sizeof(buf), "%x", UINT_MAX);
748 EXPECT_STREQ("ffffffff", buf);
749}
750
751TEST(STDIO_TEST, snprintf_X_UINT_MAX) {
752 char buf[BUFSIZ];
753 snprintf(buf, sizeof(buf), "%X", UINT_MAX);
754 EXPECT_STREQ("FFFFFFFF", buf);
755}
756
Christopher Ferris13f26a72016-01-13 13:47:58 -0800757TEST(STDIO_TEST, snprintf_e) {
Elliott Hughes4bd97ce2014-04-10 17:48:14 -0700758 char buf[BUFSIZ];
759
760 snprintf(buf, sizeof(buf), "%e", 1.5);
761 EXPECT_STREQ("1.500000e+00", buf);
762
763 snprintf(buf, sizeof(buf), "%Le", 1.5l);
764 EXPECT_STREQ("1.500000e+00", buf);
765}
766
Christopher Ferris13f26a72016-01-13 13:47:58 -0800767TEST(STDIO_TEST, snprintf_negative_zero_5084292) {
Elliott Hughese77f38f2014-05-14 12:39:12 -0700768 char buf[BUFSIZ];
769
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800770 snprintf(buf, sizeof(buf), "%e", -0.0);
771 EXPECT_STREQ("-0.000000e+00", buf);
772 snprintf(buf, sizeof(buf), "%E", -0.0);
773 EXPECT_STREQ("-0.000000E+00", buf);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700774 snprintf(buf, sizeof(buf), "%f", -0.0);
775 EXPECT_STREQ("-0.000000", buf);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800776 snprintf(buf, sizeof(buf), "%F", -0.0);
777 EXPECT_STREQ("-0.000000", buf);
778 snprintf(buf, sizeof(buf), "%g", -0.0);
779 EXPECT_STREQ("-0", buf);
780 snprintf(buf, sizeof(buf), "%G", -0.0);
781 EXPECT_STREQ("-0", buf);
782 snprintf(buf, sizeof(buf), "%a", -0.0);
783 EXPECT_STREQ("-0x0p+0", buf);
784 snprintf(buf, sizeof(buf), "%A", -0.0);
785 EXPECT_STREQ("-0X0P+0", buf);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700786}
787
Christopher Ferris13f26a72016-01-13 13:47:58 -0800788TEST(STDIO_TEST, snprintf_utf8_15439554) {
Yi Kong32bc0fc2018-08-02 17:31:13 -0700789 locale_t cloc = newlocale(LC_ALL, "C.UTF-8", nullptr);
Wally Yaua40fdbd2014-08-26 09:47:23 -0700790 locale_t old_locale = uselocale(cloc);
Dan Albert1aec7c12014-07-30 10:53:48 -0700791
Elliott Hughes69f05d22014-06-05 20:10:09 -0700792 // http://b/15439554
793 char buf[BUFSIZ];
794
795 // 1-byte character.
796 snprintf(buf, sizeof(buf), "%dx%d", 1, 2);
797 EXPECT_STREQ("1x2", buf);
798 // 2-byte character.
799 snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2);
800 EXPECT_STREQ("1¢2", buf);
801 // 3-byte character.
802 snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2);
803 EXPECT_STREQ("1€2", buf);
804 // 4-byte character.
805 snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2);
806 EXPECT_STREQ("1𤭢2", buf);
Dan Albert1aec7c12014-07-30 10:53:48 -0700807
Wally Yaua40fdbd2014-08-26 09:47:23 -0700808 uselocale(old_locale);
Dan Albert1aec7c12014-07-30 10:53:48 -0700809 freelocale(cloc);
Elliott Hughes69f05d22014-06-05 20:10:09 -0700810}
811
Elliott Hughes43f7c872016-02-05 11:18:41 -0800812static void* snprintf_small_stack_fn(void*) {
813 // Make life (realistically) hard for ourselves by allocating our own buffer for the result.
814 char buf[PATH_MAX];
815 snprintf(buf, sizeof(buf), "/proc/%d", getpid());
816 return nullptr;
817}
818
819TEST(STDIO_TEST, snprintf_small_stack) {
820 // Is it safe to call snprintf on a thread with a small stack?
821 // (The snprintf implementation puts some pretty large buffers on the stack.)
822 pthread_attr_t a;
823 ASSERT_EQ(0, pthread_attr_init(&a));
824 ASSERT_EQ(0, pthread_attr_setstacksize(&a, PTHREAD_STACK_MIN));
825
826 pthread_t t;
827 ASSERT_EQ(0, pthread_create(&t, &a, snprintf_small_stack_fn, nullptr));
828 ASSERT_EQ(0, pthread_join(t, nullptr));
829}
830
Elliott Hughes8200e552016-02-05 21:57:37 -0800831TEST(STDIO_TEST, snprintf_asterisk_overflow) {
832 char buf[128];
833 ASSERT_EQ(5, snprintf(buf, sizeof(buf), "%.*s%c", 4, "hello world", '!'));
834 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX/2, "hello world", '!'));
835 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX-1, "hello world", '!'));
836 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX, "hello world", '!'));
837 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", -1, "hello world", '!'));
838
839 // INT_MAX-1, INT_MAX, INT_MAX+1.
840 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483646s%c", "hello world", '!'));
841 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483647s%c", "hello world", '!'));
842 ASSERT_EQ(-1, snprintf(buf, sizeof(buf), "%.2147483648s%c", "hello world", '!'));
843 ASSERT_EQ(ENOMEM, errno);
844}
845
Elliott Hughes70715da2016-08-01 16:35:17 -0700846TEST(STDIO_TEST, fprintf) {
847 TemporaryFile tf;
848
849 FILE* tfile = fdopen(tf.fd, "r+");
850 ASSERT_TRUE(tfile != nullptr);
851
852 ASSERT_EQ(7, fprintf(tfile, "%d %s", 123, "abc"));
853 AssertFileIs(tfile, "123 abc");
854 fclose(tfile);
855}
856
Christopher Ferris13f26a72016-01-13 13:47:58 -0800857TEST(STDIO_TEST, fprintf_failures_7229520) {
Elliott Hughes69f05d22014-06-05 20:10:09 -0700858 // http://b/7229520
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700859 FILE* fp;
Josh Gaof6e5b582018-06-01 15:30:54 -0700860 int fd_rdonly = open("/dev/null", O_RDONLY);
861 ASSERT_NE(-1, fd_rdonly);
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700862
863 // Unbuffered case where the fprintf(3) itself fails.
864 ASSERT_NE(nullptr, fp = tmpfile());
Yi Kong32bc0fc2018-08-02 17:31:13 -0700865 setbuf(fp, nullptr);
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700866 ASSERT_EQ(4, fprintf(fp, "epic"));
Josh Gaof6e5b582018-06-01 15:30:54 -0700867 ASSERT_NE(-1, dup2(fd_rdonly, fileno(fp)));
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700868 ASSERT_EQ(-1, fprintf(fp, "fail"));
Josh Gaof6e5b582018-06-01 15:30:54 -0700869 ASSERT_EQ(0, fclose(fp));
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700870
871 // Buffered case where we won't notice until the fclose(3).
872 // It's likely this is what was actually seen in http://b/7229520,
873 // and that expecting fprintf to fail is setting yourself up for
874 // disappointment. Remember to check fclose(3)'s return value, kids!
875 ASSERT_NE(nullptr, fp = tmpfile());
876 ASSERT_EQ(4, fprintf(fp, "epic"));
Josh Gaof6e5b582018-06-01 15:30:54 -0700877 ASSERT_NE(-1, dup2(fd_rdonly, fileno(fp)));
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700878 ASSERT_EQ(4, fprintf(fp, "fail"));
879 ASSERT_EQ(-1, fclose(fp));
880}
881
Elliott Hughes468efc82018-07-10 14:39:49 -0700882TEST(STDIO_TEST, popen_r) {
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800883 FILE* fp = popen("cat /proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700884 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800885
886 char buf[16];
887 char* s = fgets(buf, sizeof(buf), fp);
888 buf[13] = '\0';
889 ASSERT_STREQ("Linux version", s);
890
891 ASSERT_EQ(0, pclose(fp));
892}
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700893
Elliott Hughes468efc82018-07-10 14:39:49 -0700894TEST(STDIO_TEST, popen_socketpair) {
895 FILE* fp = popen("cat", "r+");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700896 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -0700897
898 fputs("hello\nworld\n", fp);
899 fflush(fp);
900
901 char buf[16];
902 ASSERT_NE(nullptr, fgets(buf, sizeof(buf), fp));
903 EXPECT_STREQ("hello\n", buf);
904 ASSERT_NE(nullptr, fgets(buf, sizeof(buf), fp));
905 EXPECT_STREQ("world\n", buf);
906
907 ASSERT_EQ(0, pclose(fp));
908}
909
910TEST(STDIO_TEST, popen_socketpair_shutdown) {
911 FILE* fp = popen("uniq -c", "r+");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700912 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -0700913
914 fputs("a\na\na\na\nb\n", fp);
915 fflush(fp);
916 ASSERT_EQ(0, shutdown(fileno(fp), SHUT_WR));
917
918 char buf[16];
919 ASSERT_NE(nullptr, fgets(buf, sizeof(buf), fp));
920 EXPECT_STREQ(" 4 a\n", buf);
921 ASSERT_NE(nullptr, fgets(buf, sizeof(buf), fp));
922 EXPECT_STREQ(" 1 b\n", buf);
923
924 ASSERT_EQ(0, pclose(fp));
925}
926
927TEST(STDIO_TEST, popen_return_value_0) {
928 FILE* fp = popen("true", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700929 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -0700930 int status = pclose(fp);
931 EXPECT_TRUE(WIFEXITED(status));
932 EXPECT_EQ(0, WEXITSTATUS(status));
933}
934
935TEST(STDIO_TEST, popen_return_value_1) {
936 FILE* fp = popen("false", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700937 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -0700938 int status = pclose(fp);
939 EXPECT_TRUE(WIFEXITED(status));
940 EXPECT_EQ(1, WEXITSTATUS(status));
941}
942
943TEST(STDIO_TEST, popen_return_value_signal) {
944 FILE* fp = popen("kill -7 $$", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700945 ASSERT_TRUE(fp != nullptr);
Elliott Hughes468efc82018-07-10 14:39:49 -0700946 int status = pclose(fp);
947 EXPECT_TRUE(WIFSIGNALED(status));
948 EXPECT_EQ(7, WTERMSIG(status));
949}
950
Christopher Ferris13f26a72016-01-13 13:47:58 -0800951TEST(STDIO_TEST, getc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700952 FILE* fp = fopen("/proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700953 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700954 ASSERT_EQ('L', getc(fp));
955 ASSERT_EQ('i', getc(fp));
956 ASSERT_EQ('n', getc(fp));
957 ASSERT_EQ('u', getc(fp));
958 ASSERT_EQ('x', getc(fp));
959 fclose(fp);
960}
961
Christopher Ferris13f26a72016-01-13 13:47:58 -0800962TEST(STDIO_TEST, putc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700963 FILE* fp = fopen("/proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -0700964 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700965 ASSERT_EQ(EOF, putc('x', fp));
966 fclose(fp);
967}
Elliott Hughes603332f2014-03-12 17:10:41 -0700968
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700969TEST(STDIO_TEST, sscanf_swscanf) {
970 struct stuff {
971 char s1[123];
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -0800972 int i1, i2;
973 char cs1[3];
974 char s2[3];
975 char c1;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700976 double d1;
977 float f1;
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -0800978 char s3[123];
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700979
980 void Check() {
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -0800981 EXPECT_STREQ("hello", s1);
982 EXPECT_EQ(123, i1);
983 EXPECT_EQ(456, i2);
984 EXPECT_EQ('a', cs1[0]);
985 EXPECT_EQ('b', cs1[1]);
986 EXPECT_EQ('x', cs1[2]); // No terminating NUL.
987 EXPECT_STREQ("AB", s2); // Terminating NUL.
988 EXPECT_EQ('!', c1);
989 EXPECT_DOUBLE_EQ(1.23, d1);
990 EXPECT_FLOAT_EQ(9.0f, f1);
991 EXPECT_STREQ("world", s3);
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700992 }
993 } s;
994
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -0800995 memset(&s, 'x', sizeof(s));
996 ASSERT_EQ(9, sscanf(" hello 123 456abAB! 1.23 0x1.2p3 world",
997 "%s %i%i%2c%[A-Z]%c %lf %f %s",
998 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 -0700999 s.Check();
1000
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001001 memset(&s, 'x', sizeof(s));
1002 ASSERT_EQ(9, swscanf(L" hello 123 456abAB! 1.23 0x1.2p3 world",
1003 L"%s %i%i%2c%[A-Z]%c %lf %f %s",
1004 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 -07001005 s.Check();
Elliott Hughes603332f2014-03-12 17:10:41 -07001006}
Elliott Hughes53b24382014-05-02 18:29:25 -07001007
Elliott Hughes0d3ba1f2017-12-06 16:41:35 -08001008template <typename T>
1009static void CheckScanf(int sscanf_fn(const T*, const T*, ...),
1010 const T* input, const T* fmt,
1011 int expected_count, const char* expected_string) {
1012 char buf[256] = {};
1013 ASSERT_EQ(expected_count, sscanf_fn(input, fmt, &buf)) << fmt;
1014 ASSERT_STREQ(expected_string, buf) << fmt;
1015}
1016
1017TEST(STDIO_TEST, sscanf_ccl) {
1018 // `abc` is just those characters.
1019 CheckScanf(sscanf, "abcd", "%[abc]", 1, "abc");
1020 // `a-c` is the range 'a' .. 'c'.
1021 CheckScanf(sscanf, "abcd", "%[a-c]", 1, "abc");
1022 CheckScanf(sscanf, "-d", "%[a-c]", 0, "");
1023 CheckScanf(sscanf, "ac-bAd", "%[a--c]", 1, "ac-bA");
1024 // `a-c-e` is equivalent to `a-e`.
1025 CheckScanf(sscanf, "abcdefg", "%[a-c-e]", 1, "abcde");
1026 // `e-a` is equivalent to `ae-` (because 'e' > 'a').
1027 CheckScanf(sscanf, "-a-e-b", "%[e-a]", 1, "-a-e-");
1028 // An initial '^' negates the set.
1029 CheckScanf(sscanf, "abcde", "%[^d]", 1, "abc");
1030 CheckScanf(sscanf, "abcdefgh", "%[^c-d]", 1, "ab");
1031 CheckScanf(sscanf, "hgfedcba", "%[^c-d]", 1, "hgfe");
1032 // The first character may be ']' or '-' without being special.
1033 CheckScanf(sscanf, "[[]]x", "%[][]", 1, "[[]]");
1034 CheckScanf(sscanf, "-a-x", "%[-a]", 1, "-a-");
1035 // The last character may be '-' without being special.
1036 CheckScanf(sscanf, "-a-x", "%[a-]", 1, "-a-");
1037 // X--Y is [X--] + Y, not [X--] + [--Y] (a bug in my initial implementation).
1038 CheckScanf(sscanf, "+,-/.", "%[+--/]", 1, "+,-/");
1039}
1040
1041TEST(STDIO_TEST, swscanf_ccl) {
1042 // `abc` is just those characters.
1043 CheckScanf(swscanf, L"abcd", L"%[abc]", 1, "abc");
1044 // `a-c` is the range 'a' .. 'c'.
1045 CheckScanf(swscanf, L"abcd", L"%[a-c]", 1, "abc");
1046 CheckScanf(swscanf, L"-d", L"%[a-c]", 0, "");
1047 CheckScanf(swscanf, L"ac-bAd", L"%[a--c]", 1, "ac-bA");
1048 // `a-c-e` is equivalent to `a-e`.
1049 CheckScanf(swscanf, L"abcdefg", L"%[a-c-e]", 1, "abcde");
1050 // `e-a` is equivalent to `ae-` (because 'e' > 'a').
1051 CheckScanf(swscanf, L"-a-e-b", L"%[e-a]", 1, "-a-e-");
1052 // An initial '^' negates the set.
1053 CheckScanf(swscanf, L"abcde", L"%[^d]", 1, "abc");
1054 CheckScanf(swscanf, L"abcdefgh", L"%[^c-d]", 1, "ab");
1055 CheckScanf(swscanf, L"hgfedcba", L"%[^c-d]", 1, "hgfe");
1056 // The first character may be ']' or '-' without being special.
1057 CheckScanf(swscanf, L"[[]]x", L"%[][]", 1, "[[]]");
1058 CheckScanf(swscanf, L"-a-x", L"%[-a]", 1, "-a-");
1059 // The last character may be '-' without being special.
1060 CheckScanf(swscanf, L"-a-x", L"%[a-]", 1, "-a-");
1061 // X--Y is [X--] + Y, not [X--] + [--Y] (a bug in my initial implementation).
1062 CheckScanf(swscanf, L"+,-/.", L"%[+--/]", 1, "+,-/");
1063}
1064
Elliott Hughes38e4aef2018-01-18 10:21:29 -08001065template <typename T1, typename T2>
1066static void CheckScanfM(int sscanf_fn(const T1*, const T1*, ...),
1067 const T1* input, const T1* fmt,
1068 int expected_count, const T2* expected_string) {
1069 T2* result = nullptr;
1070 ASSERT_EQ(expected_count, sscanf_fn(input, fmt, &result)) << fmt;
1071 if (expected_string == nullptr) {
1072 ASSERT_EQ(nullptr, result);
1073 } else {
1074 ASSERT_STREQ(expected_string, result) << fmt;
1075 }
1076 free(result);
1077}
1078
1079TEST(STDIO_TEST, sscanf_mc) {
1080 char* p1 = nullptr;
1081 char* p2 = nullptr;
1082 ASSERT_EQ(2, sscanf("hello", "%mc%mc", &p1, &p2));
1083 ASSERT_EQ('h', *p1);
1084 ASSERT_EQ('e', *p2);
1085 free(p1);
1086 free(p2);
1087
1088 p1 = nullptr;
1089 ASSERT_EQ(1, sscanf("hello", "%4mc", &p1));
1090 ASSERT_EQ('h', p1[0]);
1091 ASSERT_EQ('e', p1[1]);
1092 ASSERT_EQ('l', p1[2]);
1093 ASSERT_EQ('l', p1[3]);
1094 free(p1);
1095
1096 p1 = nullptr;
1097 ASSERT_EQ(1, sscanf("hello world", "%30mc", &p1));
1098 ASSERT_EQ('h', p1[0]);
1099 ASSERT_EQ('e', p1[1]);
1100 ASSERT_EQ('l', p1[2]);
1101 ASSERT_EQ('l', p1[3]);
1102 ASSERT_EQ('o', p1[4]);
1103 free(p1);
1104}
1105
1106
1107TEST(STDIO_TEST, sscanf_mlc) {
1108 // This is so useless that clang doesn't even believe it exists...
1109#pragma clang diagnostic push
1110#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
1111#pragma clang diagnostic ignored "-Wformat-extra-args"
1112
1113 wchar_t* p1 = nullptr;
1114 wchar_t* p2 = nullptr;
1115 ASSERT_EQ(2, sscanf("hello", "%mlc%mlc", &p1, &p2));
1116 ASSERT_EQ(L'h', *p1);
1117 ASSERT_EQ(L'e', *p2);
1118 free(p1);
1119 free(p2);
1120
1121 p1 = nullptr;
1122 ASSERT_EQ(1, sscanf("hello", "%4mlc", &p1));
1123 ASSERT_EQ(L'h', p1[0]);
1124 ASSERT_EQ(L'e', p1[1]);
1125 ASSERT_EQ(L'l', p1[2]);
1126 ASSERT_EQ(L'l', p1[3]);
1127 free(p1);
1128
1129 p1 = nullptr;
1130 ASSERT_EQ(1, sscanf("hello world", "%30mlc", &p1));
1131 ASSERT_EQ(L'h', p1[0]);
1132 ASSERT_EQ(L'e', p1[1]);
1133 ASSERT_EQ(L'l', p1[2]);
1134 ASSERT_EQ(L'l', p1[3]);
1135 ASSERT_EQ(L'o', p1[4]);
1136 free(p1);
1137#pragma clang diagnostic pop
1138}
1139
1140
1141TEST(STDIO_TEST, sscanf_ms) {
1142 CheckScanfM(sscanf, "hello", "%ms", 1, "hello");
1143 CheckScanfM(sscanf, "hello", "%4ms", 1, "hell");
1144 CheckScanfM(sscanf, "hello world", "%30ms", 1, "hello");
1145}
1146
1147TEST(STDIO_TEST, sscanf_mls) {
1148 CheckScanfM(sscanf, "hello", "%mls", 1, L"hello");
1149 CheckScanfM(sscanf, "hello", "%4mls", 1, L"hell");
1150 CheckScanfM(sscanf, "hello world", "%30mls", 1, L"hello");
1151}
1152
1153TEST(STDIO_TEST, sscanf_m_ccl) {
1154 CheckScanfM(sscanf, "hello", "%m[a-z]", 1, "hello");
1155 CheckScanfM(sscanf, "hello", "%4m[a-z]", 1, "hell");
1156 CheckScanfM(sscanf, "hello world", "%30m[a-z]", 1, "hello");
1157}
1158
1159TEST(STDIO_TEST, sscanf_ml_ccl) {
1160 CheckScanfM(sscanf, "hello", "%ml[a-z]", 1, L"hello");
1161 CheckScanfM(sscanf, "hello", "%4ml[a-z]", 1, L"hell");
1162 CheckScanfM(sscanf, "hello world", "%30ml[a-z]", 1, L"hello");
1163}
1164
1165TEST(STDIO_TEST, sscanf_ls) {
1166 wchar_t w[32] = {};
1167 ASSERT_EQ(1, sscanf("hello world", "%ls", w));
1168 ASSERT_EQ(L"hello", std::wstring(w));
1169}
1170
1171TEST(STDIO_TEST, sscanf_ls_suppress) {
1172 ASSERT_EQ(0, sscanf("hello world", "%*ls %*ls"));
1173}
1174
1175TEST(STDIO_TEST, sscanf_ls_n) {
1176 setlocale(LC_ALL, "C.UTF-8");
1177 wchar_t w[32] = {};
1178 int pos = 0;
1179 ASSERT_EQ(1, sscanf("\xc4\x80", "%ls%n", w, &pos));
1180 ASSERT_EQ(static_cast<wchar_t>(256), w[0]);
1181 ASSERT_EQ(2, pos);
1182}
1183
1184TEST(STDIO_TEST, sscanf_ls_realloc) {
1185 // This is so useless that clang doesn't even believe it exists...
1186#pragma clang diagnostic push
1187#pragma clang diagnostic ignored "-Wformat-invalid-specifier"
1188#pragma clang diagnostic ignored "-Wformat-extra-args"
1189 wchar_t* p1 = nullptr;
1190 wchar_t* p2 = nullptr;
1191 ASSERT_EQ(2, sscanf("1234567890123456789012345678901234567890 world", "%mls %mls", &p1, &p2));
1192 ASSERT_EQ(L"1234567890123456789012345678901234567890", std::wstring(p1));
1193 ASSERT_EQ(L"world", std::wstring(p2));
1194#pragma clang diagnostic pop
1195}
1196
Elliott Hughesbf9cb9e2017-12-11 12:39:01 -08001197// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=202240
1198TEST(STDIO_TEST, scanf_wscanf_EOF) {
1199 EXPECT_EQ(0, sscanf("b", "ab"));
1200 EXPECT_EQ(EOF, sscanf("", "a"));
1201 EXPECT_EQ(0, swscanf(L"b", L"ab"));
1202 EXPECT_EQ(EOF, swscanf(L"", L"a"));
1203}
1204
1205TEST(STDIO_TEST, scanf_invalid_UTF8) {
1206#if 0 // TODO: more tests invented during code review; no regressions, so fix later.
1207 char buf[BUFSIZ];
1208 wchar_t wbuf[BUFSIZ];
1209
1210 memset(buf, 0, sizeof(buf));
1211 memset(wbuf, 0, sizeof(wbuf));
1212 EXPECT_EQ(0, sscanf("\xc0" " foo", "%ls %s", wbuf, buf));
1213#endif
1214}
1215
1216TEST(STDIO_TEST, scanf_no_match_no_termination) {
1217 char buf[4] = "x";
1218 EXPECT_EQ(0, sscanf("d", "%[abc]", buf));
1219 EXPECT_EQ('x', buf[0]);
1220 EXPECT_EQ(0, swscanf(L"d", L"%[abc]", buf));
1221 EXPECT_EQ('x', buf[0]);
1222
1223 wchar_t wbuf[4] = L"x";
1224 EXPECT_EQ(0, swscanf(L"d", L"%l[abc]", wbuf));
1225 EXPECT_EQ(L'x', wbuf[0]);
1226
1227 EXPECT_EQ(EOF, sscanf("", "%s", buf));
1228 EXPECT_EQ('x', buf[0]);
1229
1230 EXPECT_EQ(EOF, swscanf(L"", L"%ls", wbuf));
1231 EXPECT_EQ(L'x', wbuf[0]);
1232}
1233
1234TEST(STDIO_TEST, scanf_wscanf_wide_character_class) {
1235#if 0 // TODO: more tests invented during code review; no regressions, so fix later.
1236 wchar_t buf[BUFSIZ];
1237
1238 // A wide character shouldn't match an ASCII-only class for scanf or wscanf.
1239 memset(buf, 0, sizeof(buf));
1240 EXPECT_EQ(1, sscanf("xĀyz", "%l[xy]", buf));
1241 EXPECT_EQ(L"x"s, std::wstring(buf));
1242 memset(buf, 0, sizeof(buf));
1243 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[xy]", buf));
1244 EXPECT_EQ(L"x"s, std::wstring(buf));
1245
1246 // Even if scanf has wide characters in a class, they won't match...
1247 // TODO: is that a bug?
1248 memset(buf, 0, sizeof(buf));
1249 EXPECT_EQ(1, sscanf("xĀyz", "%l[xĀy]", buf));
1250 EXPECT_EQ(L"x"s, std::wstring(buf));
1251 // ...unless you use wscanf.
1252 memset(buf, 0, sizeof(buf));
1253 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[xĀy]", buf));
1254 EXPECT_EQ(L"xĀy"s, std::wstring(buf));
1255
1256 // Negation only covers ASCII for scanf...
1257 memset(buf, 0, sizeof(buf));
1258 EXPECT_EQ(1, sscanf("xĀyz", "%l[^ab]", buf));
1259 EXPECT_EQ(L"x"s, std::wstring(buf));
1260 // ...but covers wide characters for wscanf.
1261 memset(buf, 0, sizeof(buf));
1262 EXPECT_EQ(1, swscanf(L"xĀyz", L"%l[^ab]", buf));
1263 EXPECT_EQ(L"xĀyz"s, std::wstring(buf));
1264
1265 // We already determined that non-ASCII characters are ignored in scanf classes.
1266 memset(buf, 0, sizeof(buf));
1267 EXPECT_EQ(1, sscanf("x"
1268 "\xc4\x80" // Matches a byte from each wide char in the class.
1269 "\xc6\x82" // Neither byte is in the class.
1270 "yz",
1271 "%l[xy" "\xc5\x80" "\xc4\x81" "]", buf));
1272 EXPECT_EQ(L"x", std::wstring(buf));
1273 // bionic and glibc both behave badly for wscanf, so let's call it right for now...
1274 memset(buf, 0, sizeof(buf));
1275 EXPECT_EQ(1, swscanf(L"x"
1276 L"\xc4\x80"
1277 L"\xc6\x82"
1278 L"yz",
1279 L"%l[xy" L"\xc5\x80" L"\xc4\x81" L"]", buf));
1280 // Note that this isn't L"xĀ" --- although the *bytes* matched, they're
1281 // not put back together as a wide character.
1282 EXPECT_EQ(L"x" L"\xc4" L"\x80", std::wstring(buf));
1283#endif
1284}
1285
Christopher Ferris13f26a72016-01-13 13:47:58 -08001286TEST(STDIO_TEST, cantwrite_EBADF) {
Elliott Hughes53b24382014-05-02 18:29:25 -07001287 // If we open a file read-only...
1288 FILE* fp = fopen("/proc/version", "r");
1289
1290 // ...all attempts to write to that file should return failure.
1291
1292 // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
1293 // glibc gets the wide-character functions wrong.
1294
1295 errno = 0;
1296 EXPECT_EQ(EOF, putc('x', fp));
1297 EXPECT_EQ(EBADF, errno);
1298
1299 errno = 0;
1300 EXPECT_EQ(EOF, fprintf(fp, "hello"));
1301 EXPECT_EQ(EBADF, errno);
1302
1303 errno = 0;
1304 EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
Elliott Hughes063525c2014-05-13 11:19:57 -07001305#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -07001306 EXPECT_EQ(EBADF, errno);
1307#endif
1308
1309 errno = 0;
Elliott Hughes53b24382014-05-02 18:29:25 -07001310 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
1311 EXPECT_EQ(EBADF, errno);
1312
1313 errno = 0;
1314 EXPECT_EQ(EOF, fputs("hello", fp));
1315 EXPECT_EQ(EBADF, errno);
1316
1317 errno = 0;
1318 EXPECT_EQ(WEOF, fputwc(L'x', fp));
Elliott Hughes063525c2014-05-13 11:19:57 -07001319#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -07001320 EXPECT_EQ(EBADF, errno);
1321#endif
1322}
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001323
1324// Tests that we can only have a consistent and correct fpos_t when using
1325// f*pos functions (i.e. fpos doesn't get inside a multi byte character).
Christopher Ferris13f26a72016-01-13 13:47:58 -08001326TEST(STDIO_TEST, consistent_fpos_t) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001327 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
1328 uselocale(LC_GLOBAL_LOCALE);
1329
1330 FILE* fp = tmpfile();
Yi Kong32bc0fc2018-08-02 17:31:13 -07001331 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001332
1333 wchar_t mb_one_bytes = L'h';
1334 wchar_t mb_two_bytes = 0x00a2;
1335 wchar_t mb_three_bytes = 0x20ac;
1336 wchar_t mb_four_bytes = 0x24b62;
1337
1338 // Write to file.
1339 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp)));
1340 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
1341 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
1342 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
1343
1344 rewind(fp);
1345
1346 // Record each character position.
1347 fpos_t pos1;
1348 fpos_t pos2;
1349 fpos_t pos3;
1350 fpos_t pos4;
1351 fpos_t pos5;
1352 EXPECT_EQ(0, fgetpos(fp, &pos1));
1353 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
1354 EXPECT_EQ(0, fgetpos(fp, &pos2));
1355 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1356 EXPECT_EQ(0, fgetpos(fp, &pos3));
1357 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
1358 EXPECT_EQ(0, fgetpos(fp, &pos4));
1359 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
1360 EXPECT_EQ(0, fgetpos(fp, &pos5));
1361
Elliott Hughes063525c2014-05-13 11:19:57 -07001362#if defined(__BIONIC__)
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001363 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD
1364 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In
1365 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE
1366 // structure.
1367 ASSERT_EQ(0, static_cast<off_t>(pos1));
1368 ASSERT_EQ(1, static_cast<off_t>(pos2));
1369 ASSERT_EQ(3, static_cast<off_t>(pos3));
1370 ASSERT_EQ(6, static_cast<off_t>(pos4));
1371 ASSERT_EQ(10, static_cast<off_t>(pos5));
1372#endif
1373
1374 // Exercise back and forth movements of the position.
1375 ASSERT_EQ(0, fsetpos(fp, &pos2));
1376 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1377 ASSERT_EQ(0, fsetpos(fp, &pos1));
1378 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
1379 ASSERT_EQ(0, fsetpos(fp, &pos4));
1380 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
1381 ASSERT_EQ(0, fsetpos(fp, &pos3));
1382 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
1383 ASSERT_EQ(0, fsetpos(fp, &pos5));
1384 ASSERT_EQ(WEOF, fgetwc(fp));
1385
1386 fclose(fp);
1387}
1388
1389// Exercise the interaction between fpos and seek.
Christopher Ferris13f26a72016-01-13 13:47:58 -08001390TEST(STDIO_TEST, fpos_t_and_seek) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001391 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
1392 uselocale(LC_GLOBAL_LOCALE);
1393
Calin Juravle9b95ea92014-05-14 17:07:10 +01001394 // In glibc-2.16 fseek doesn't work properly in wide mode
1395 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is
1396 // to close and re-open the file. We do it in order to make the test pass
1397 // with all glibcs.
1398
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001399 TemporaryFile tf;
1400 FILE* fp = fdopen(tf.fd, "w+");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001401 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001402
1403 wchar_t mb_two_bytes = 0x00a2;
1404 wchar_t mb_three_bytes = 0x20ac;
1405 wchar_t mb_four_bytes = 0x24b62;
1406
1407 // Write to file.
1408 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
1409 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
1410 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
1411
1412 fflush(fp);
1413 fclose(fp);
1414
1415 fp = fopen(tf.filename, "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001416 ASSERT_TRUE(fp != nullptr);
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001417
1418 // Store a valid position.
1419 fpos_t mb_two_bytes_pos;
1420 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos));
1421
1422 // Move inside mb_four_bytes with fseek.
1423 long offset_inside_mb = 6;
1424 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET));
1425
1426 // Store the "inside multi byte" position.
1427 fpos_t pos_inside_mb;
1428 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb));
Elliott Hughes063525c2014-05-13 11:19:57 -07001429#if defined(__BIONIC__)
1430 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb));
1431#endif
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001432
1433 // Reading from within a byte should produce an error.
1434 ASSERT_EQ(WEOF, fgetwc(fp));
1435 ASSERT_EQ(EILSEQ, errno);
1436
1437 // Reverting to a valid position should work.
1438 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos));
1439 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
1440
1441 // Moving withing a multi byte with fsetpos should work but reading should
1442 // produce an error.
1443 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb));
1444 ASSERT_EQ(WEOF, fgetwc(fp));
1445 ASSERT_EQ(EILSEQ, errno);
1446
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001447 ASSERT_EQ(0, fclose(fp));
Calin Juravle03e4ebe2014-05-08 14:42:06 +01001448}
Elliott Hughes6b841db2014-08-20 16:10:49 -07001449
Christopher Ferris13f26a72016-01-13 13:47:58 -08001450TEST(STDIO_TEST, fmemopen) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001451 char buf[16];
1452 memset(buf, 0, sizeof(buf));
1453 FILE* fp = fmemopen(buf, sizeof(buf), "r+");
1454 ASSERT_EQ('<', fputc('<', fp));
1455 ASSERT_NE(EOF, fputs("abc>\n", fp));
1456 fflush(fp);
1457
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001458 // We wrote to the buffer...
Elliott Hughes6b841db2014-08-20 16:10:49 -07001459 ASSERT_STREQ("<abc>\n", buf);
1460
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001461 // And can read back from the file.
Elliott Hughes70715da2016-08-01 16:35:17 -07001462 AssertFileIs(fp, "<abc>\n", true);
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001463 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001464}
1465
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001466TEST(STDIO_TEST, fmemopen_nullptr) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001467 FILE* fp = fmemopen(nullptr, 128, "r+");
1468 ASSERT_NE(EOF, fputs("xyz\n", fp));
1469
Elliott Hughes70715da2016-08-01 16:35:17 -07001470 AssertFileIs(fp, "xyz\n", true);
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001471 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001472}
1473
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001474TEST(STDIO_TEST, fmemopen_trailing_NUL_byte) {
1475 FILE* fp;
1476 char buf[8];
1477
1478 // POSIX: "When a stream open for writing is flushed or closed, a null byte
1479 // shall be written at the current position or at the end of the buffer,
1480 // depending on the size of the contents."
1481 memset(buf, 'x', sizeof(buf));
1482 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w"));
1483 // Even with nothing written (and not in truncate mode), we'll flush a NUL...
1484 ASSERT_EQ(0, fflush(fp));
1485 EXPECT_EQ("\0xxxxxxx"s, std::string(buf, buf + sizeof(buf)));
1486 // Now write and check that the NUL moves along with our writes...
1487 ASSERT_NE(EOF, fputs("hello", fp));
1488 ASSERT_EQ(0, fflush(fp));
1489 EXPECT_EQ("hello\0xx"s, std::string(buf, buf + sizeof(buf)));
1490 ASSERT_NE(EOF, fputs("wo", fp));
1491 ASSERT_EQ(0, fflush(fp));
1492 EXPECT_EQ("hellowo\0"s, std::string(buf, buf + sizeof(buf)));
1493 ASSERT_EQ(0, fclose(fp));
1494
1495 // "If a stream open for update is flushed or closed and the last write has
1496 // advanced the current buffer size, a null byte shall be written at the end
1497 // of the buffer if it fits."
1498 memset(buf, 'x', sizeof(buf));
1499 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r+"));
1500 // Nothing written yet, so no advance...
1501 ASSERT_EQ(0, fflush(fp));
1502 EXPECT_EQ("xxxxxxxx"s, std::string(buf, buf + sizeof(buf)));
1503 ASSERT_NE(EOF, fputs("hello", fp));
1504 ASSERT_EQ(0, fclose(fp));
1505}
1506
1507TEST(STDIO_TEST, fmemopen_size) {
1508 FILE* fp;
Elliott Hughes6b841db2014-08-20 16:10:49 -07001509 char buf[16];
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001510 memset(buf, 'x', sizeof(buf));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001511
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001512 // POSIX: "The stream shall also maintain the size of the current buffer
1513 // contents; use of fseek() or fseeko() on the stream with SEEK_END shall
1514 // seek relative to this size."
Elliott Hughes6b841db2014-08-20 16:10:49 -07001515
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001516 // "For modes r and r+ the size shall be set to the value given by the size
1517 // argument."
1518 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "r"));
1519 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1520 EXPECT_EQ(16, ftell(fp));
1521 EXPECT_EQ(16, ftello(fp));
1522 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1523 EXPECT_EQ(16, ftell(fp));
1524 EXPECT_EQ(16, ftello(fp));
1525 ASSERT_EQ(0, fclose(fp));
1526 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "r+"));
1527 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1528 EXPECT_EQ(16, ftell(fp));
1529 EXPECT_EQ(16, ftello(fp));
1530 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1531 EXPECT_EQ(16, ftell(fp));
1532 EXPECT_EQ(16, ftello(fp));
1533 ASSERT_EQ(0, fclose(fp));
1534
1535 // "For modes w and w+ the initial size shall be zero..."
1536 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w"));
1537 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1538 EXPECT_EQ(0, ftell(fp));
1539 EXPECT_EQ(0, ftello(fp));
1540 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1541 EXPECT_EQ(0, ftell(fp));
1542 EXPECT_EQ(0, ftello(fp));
1543 ASSERT_EQ(0, fclose(fp));
1544 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w+"));
1545 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1546 EXPECT_EQ(0, ftell(fp));
1547 EXPECT_EQ(0, ftello(fp));
1548 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1549 EXPECT_EQ(0, ftell(fp));
1550 EXPECT_EQ(0, ftello(fp));
1551 ASSERT_EQ(0, fclose(fp));
1552
1553 // "...and for modes a and a+ the initial size shall be:
1554 // 1. Zero, if buf is a null pointer
1555 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "a"));
1556 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1557 EXPECT_EQ(0, ftell(fp));
1558 EXPECT_EQ(0, ftello(fp));
1559 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1560 EXPECT_EQ(0, ftell(fp));
1561 EXPECT_EQ(0, ftello(fp));
1562 ASSERT_EQ(0, fclose(fp));
1563 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "a+"));
1564 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1565 EXPECT_EQ(0, ftell(fp));
1566 EXPECT_EQ(0, ftello(fp));
1567 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1568 EXPECT_EQ(0, ftell(fp));
1569 EXPECT_EQ(0, ftello(fp));
1570 ASSERT_EQ(0, fclose(fp));
1571
1572 // 2. The position of the first null byte in the buffer, if one is found
1573 memset(buf, 'x', sizeof(buf));
1574 buf[3] = '\0';
1575 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a"));
1576 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1577 EXPECT_EQ(3, ftell(fp));
1578 EXPECT_EQ(3, ftello(fp));
1579 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1580 EXPECT_EQ(3, ftell(fp));
1581 EXPECT_EQ(3, ftello(fp));
1582 ASSERT_EQ(0, fclose(fp));
1583 memset(buf, 'x', sizeof(buf));
1584 buf[3] = '\0';
1585 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a+"));
1586 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1587 EXPECT_EQ(3, ftell(fp));
1588 EXPECT_EQ(3, ftello(fp));
1589 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1590 EXPECT_EQ(3, ftell(fp));
1591 EXPECT_EQ(3, ftello(fp));
1592 ASSERT_EQ(0, fclose(fp));
1593
1594 // 3. The value of the size argument, if buf is not a null pointer and no
1595 // null byte is found.
1596 memset(buf, 'x', sizeof(buf));
1597 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a"));
1598 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1599 EXPECT_EQ(16, ftell(fp));
1600 EXPECT_EQ(16, ftello(fp));
1601 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1602 EXPECT_EQ(16, ftell(fp));
1603 EXPECT_EQ(16, ftello(fp));
1604 ASSERT_EQ(0, fclose(fp));
1605 memset(buf, 'x', sizeof(buf));
1606 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a+"));
1607 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1608 EXPECT_EQ(16, ftell(fp));
1609 EXPECT_EQ(16, ftello(fp));
1610 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1611 EXPECT_EQ(16, ftell(fp));
1612 EXPECT_EQ(16, ftello(fp));
1613 ASSERT_EQ(0, fclose(fp));
1614}
1615
1616TEST(STDIO_TEST, fmemopen_SEEK_END) {
1617 // fseek SEEK_END is relative to the current string length, not the buffer size.
1618 FILE* fp;
1619 char buf[8];
1620 memset(buf, 'x', sizeof(buf));
1621 strcpy(buf, "str");
1622 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1623 ASSERT_NE(EOF, fputs("string", fp));
1624 EXPECT_EQ(0, fseek(fp, 0, SEEK_END));
1625 EXPECT_EQ(static_cast<long>(strlen("string")), ftell(fp));
1626 EXPECT_EQ(static_cast<off_t>(strlen("string")), ftello(fp));
1627 EXPECT_EQ(0, fclose(fp));
1628
1629 // glibc < 2.22 interpreted SEEK_END the wrong way round (subtracting rather
1630 // than adding).
1631 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1632 ASSERT_NE(EOF, fputs("54321", fp));
1633 EXPECT_EQ(0, fseek(fp, -2, SEEK_END));
1634 EXPECT_EQ('2', fgetc(fp));
1635 EXPECT_EQ(0, fclose(fp));
1636}
1637
1638TEST(STDIO_TEST, fmemopen_seek_invalid) {
1639 char buf[8];
1640 memset(buf, 'x', sizeof(buf));
1641 FILE* fp = fmemopen(buf, sizeof(buf), "w");
1642 ASSERT_TRUE(fp != nullptr);
1643
1644 // POSIX: "An attempt to seek ... to a negative position or to a position
1645 // larger than the buffer size given in the size argument shall fail."
1646 // (There's no mention of what errno should be set to, and glibc doesn't
1647 // set errno in any of these cases.)
1648 EXPECT_EQ(-1, fseek(fp, -2, SEEK_SET));
1649 EXPECT_EQ(-1, fseeko(fp, -2, SEEK_SET));
1650 EXPECT_EQ(-1, fseek(fp, sizeof(buf) + 1, SEEK_SET));
1651 EXPECT_EQ(-1, fseeko(fp, sizeof(buf) + 1, SEEK_SET));
1652}
1653
1654TEST(STDIO_TEST, fmemopen_read_EOF) {
1655 // POSIX: "A read operation on the stream shall not advance the current
1656 // buffer position beyond the current buffer size."
1657 char buf[8];
1658 memset(buf, 'x', sizeof(buf));
1659 FILE* fp = fmemopen(buf, sizeof(buf), "r");
1660 ASSERT_TRUE(fp != nullptr);
1661 char buf2[BUFSIZ];
1662 ASSERT_EQ(8U, fread(buf2, 1, sizeof(buf2), fp));
1663 // POSIX: "Reaching the buffer size in a read operation shall count as
1664 // end-of-file.
1665 ASSERT_TRUE(feof(fp));
1666 ASSERT_EQ(EOF, fgetc(fp));
1667 ASSERT_EQ(0, fclose(fp));
1668}
1669
1670TEST(STDIO_TEST, fmemopen_read_null_bytes) {
1671 // POSIX: "Null bytes in the buffer shall have no special meaning for reads."
1672 char buf[] = "h\0e\0l\0l\0o";
1673 FILE* fp = fmemopen(buf, sizeof(buf), "r");
1674 ASSERT_TRUE(fp != nullptr);
1675 ASSERT_EQ('h', fgetc(fp));
1676 ASSERT_EQ(0, fgetc(fp));
1677 ASSERT_EQ('e', fgetc(fp));
1678 ASSERT_EQ(0, fgetc(fp));
1679 ASSERT_EQ('l', fgetc(fp));
1680 ASSERT_EQ(0, fgetc(fp));
1681 // POSIX: "The read operation shall start at the current buffer position of
1682 // the stream."
1683 char buf2[8];
1684 memset(buf2, 'x', sizeof(buf2));
1685 ASSERT_EQ(4U, fread(buf2, 1, sizeof(buf2), fp));
1686 ASSERT_EQ('l', buf2[0]);
1687 ASSERT_EQ(0, buf2[1]);
1688 ASSERT_EQ('o', buf2[2]);
1689 ASSERT_EQ(0, buf2[3]);
1690 for (size_t i = 4; i < sizeof(buf2); ++i) ASSERT_EQ('x', buf2[i]) << i;
1691 ASSERT_TRUE(feof(fp));
1692 ASSERT_EQ(0, fclose(fp));
1693}
1694
1695TEST(STDIO_TEST, fmemopen_write) {
1696 FILE* fp;
1697 char buf[8];
1698
1699 // POSIX: "A write operation shall start either at the current position of
1700 // the stream (if mode has not specified 'a' as the first character)..."
1701 memset(buf, 'x', sizeof(buf));
1702 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r+"));
1703 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1704 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
1705 ASSERT_EQ(' ', fputc(' ', fp));
1706 EXPECT_EQ("xx xxxxx", std::string(buf, buf + sizeof(buf)));
1707 ASSERT_EQ(0, fclose(fp));
1708
1709 // "...or at the current size of the stream (if mode had 'a' as the first
1710 // character)." (See the fmemopen_size test for what "size" means, but for
1711 // mode "a", it's the first NUL byte.)
1712 memset(buf, 'x', sizeof(buf));
1713 buf[3] = '\0';
1714 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a+"));
1715 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1716 ASSERT_EQ(' ', fputc(' ', fp));
1717 EXPECT_EQ("xxx \0xxx"s, std::string(buf, buf + sizeof(buf)));
1718 ASSERT_EQ(0, fclose(fp));
1719
1720 // "If the current position at the end of the write is larger than the
1721 // current buffer size, the current buffer size shall be set to the current
1722 // position." (See the fmemopen_size test for what "size" means, but to
1723 // query it we SEEK_END with offset 0, and then ftell.)
1724 memset(buf, 'x', sizeof(buf));
1725 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1726 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1727 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1728 EXPECT_EQ(0, ftell(fp));
1729 ASSERT_EQ(' ', fputc(' ', fp));
1730 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1731 EXPECT_EQ(1, ftell(fp));
1732 ASSERT_NE(EOF, fputs("123", fp));
1733 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1734 EXPECT_EQ(4, ftell(fp));
1735 EXPECT_EQ(" 123\0xxx"s, std::string(buf, buf + sizeof(buf)));
1736 ASSERT_EQ(0, fclose(fp));
1737}
1738
1739TEST(STDIO_TEST, fmemopen_write_EOF) {
1740 // POSIX: "A write operation on the stream shall not advance the current
1741 // buffer size beyond the size given in the size argument."
1742 FILE* fp;
1743
1744 // Scalar writes...
1745 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 4, "w"));
1746 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1747 ASSERT_EQ('x', fputc('x', fp));
1748 ASSERT_EQ('x', fputc('x', fp));
1749 ASSERT_EQ('x', fputc('x', fp));
1750 ASSERT_EQ(EOF, fputc('x', fp)); // Only 3 fit because of the implicit NUL.
1751 ASSERT_EQ(0, fclose(fp));
1752
1753 // Vector writes...
1754 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 4, "w"));
1755 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1756 ASSERT_EQ(3U, fwrite("xxxx", 1, 4, fp));
1757 ASSERT_EQ(0, fclose(fp));
1758}
1759
1760TEST(STDIO_TEST, fmemopen_initial_position) {
1761 // POSIX: "The ... current position in the buffer ... shall be initially
1762 // set to either the beginning of the buffer (for r and w modes) ..."
1763 char buf[] = "hello\0world";
1764 FILE* fp;
1765 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r"));
1766 EXPECT_EQ(0L, ftell(fp));
1767 EXPECT_EQ(0, fclose(fp));
1768 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w"));
1769 EXPECT_EQ(0L, ftell(fp));
1770 EXPECT_EQ(0, fclose(fp));
1771 buf[0] = 'h'; // (Undo the effects of the above.)
1772
1773 // POSIX: "...or to the first null byte in the buffer (for a modes)."
1774 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1775 EXPECT_EQ(5L, ftell(fp));
1776 EXPECT_EQ(0, fclose(fp));
1777
1778 // POSIX: "If no null byte is found in append mode, the initial position
1779 // shall be set to one byte after the end of the buffer."
1780 memset(buf, 'x', sizeof(buf));
1781 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1782 EXPECT_EQ(static_cast<long>(sizeof(buf)), ftell(fp));
1783 EXPECT_EQ(0, fclose(fp));
1784}
1785
1786TEST(STDIO_TEST, fmemopen_initial_position_allocated) {
1787 // POSIX: "If buf is a null pointer, the initial position shall always be
1788 // set to the beginning of the buffer."
1789 FILE* fp = fmemopen(nullptr, 128, "a+");
1790 ASSERT_TRUE(fp != nullptr);
1791 EXPECT_EQ(0L, ftell(fp));
1792 EXPECT_EQ(0L, fseek(fp, 0, SEEK_SET));
1793 EXPECT_EQ(0, fclose(fp));
1794}
1795
1796TEST(STDIO_TEST, fmemopen_zero_length) {
1797 // POSIX says it's up to the implementation whether or not you can have a
1798 // zero-length buffer (but "A future version of this standard may require
1799 // support of zero-length buffer streams explicitly"). BSD and glibc < 2.22
1800 // agreed that you couldn't, but glibc >= 2.22 allows it for consistency.
1801 FILE* fp;
1802 char buf[16];
1803 ASSERT_NE(nullptr, fp = fmemopen(buf, 0, "r+"));
1804 ASSERT_EQ(EOF, fgetc(fp));
1805 ASSERT_TRUE(feof(fp));
1806 ASSERT_EQ(0, fclose(fp));
1807 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 0, "r+"));
1808 ASSERT_EQ(EOF, fgetc(fp));
1809 ASSERT_TRUE(feof(fp));
1810 ASSERT_EQ(0, fclose(fp));
1811
1812 ASSERT_NE(nullptr, fp = fmemopen(buf, 0, "w+"));
1813 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1814 ASSERT_EQ(EOF, fputc('x', fp));
1815 ASSERT_EQ(0, fclose(fp));
1816 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 0, "w+"));
1817 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1818 ASSERT_EQ(EOF, fputc('x', fp));
1819 ASSERT_EQ(0, fclose(fp));
1820}
1821
1822TEST(STDIO_TEST, fmemopen_write_only_allocated) {
1823 // POSIX says fmemopen "may fail if the mode argument does not include a '+'".
1824 // BSD fails, glibc doesn't. We side with the more lenient.
1825 FILE* fp;
1826 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "r"));
1827 ASSERT_EQ(0, fclose(fp));
1828 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w"));
1829 ASSERT_EQ(0, fclose(fp));
1830}
1831
1832TEST(STDIO_TEST, fmemopen_fileno) {
1833 // There's no fd backing an fmemopen FILE*.
1834 FILE* fp = fmemopen(nullptr, 16, "r");
1835 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b841db2014-08-20 16:10:49 -07001836 errno = 0;
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001837 ASSERT_EQ(-1, fileno(fp));
1838 ASSERT_EQ(EBADF, errno);
1839 ASSERT_EQ(0, fclose(fp));
1840}
1841
1842TEST(STDIO_TEST, fmemopen_append_after_seek) {
1843 // In BSD and glibc < 2.22, append mode didn't force writes to append if
1844 // there had been an intervening seek.
1845
1846 FILE* fp;
1847 char buf[] = "hello\0world";
1848 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1849 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1850 ASSERT_EQ(0, fseek(fp, 0, SEEK_SET));
1851 ASSERT_NE(EOF, fputc('!', fp));
1852 EXPECT_EQ("hello!\0orld\0"s, std::string(buf, buf + sizeof(buf)));
1853 ASSERT_EQ(0, fclose(fp));
1854
1855 memcpy(buf, "hello\0world", sizeof(buf));
1856 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a+"));
1857 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1858 ASSERT_EQ(0, fseek(fp, 0, SEEK_SET));
1859 ASSERT_NE(EOF, fputc('!', fp));
1860 EXPECT_EQ("hello!\0orld\0"s, std::string(buf, buf + sizeof(buf)));
1861 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001862}
1863
Christopher Ferris13f26a72016-01-13 13:47:58 -08001864TEST(STDIO_TEST, open_memstream) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001865 char* p = nullptr;
1866 size_t size = 0;
1867 FILE* fp = open_memstream(&p, &size);
1868 ASSERT_NE(EOF, fputs("hello, world!", fp));
1869 fclose(fp);
1870
1871 ASSERT_STREQ("hello, world!", p);
1872 ASSERT_EQ(strlen("hello, world!"), size);
1873 free(p);
1874}
1875
Christopher Ferris13f26a72016-01-13 13:47:58 -08001876TEST(STDIO_TEST, open_memstream_EINVAL) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001877#if defined(__BIONIC__)
1878 char* p;
1879 size_t size;
1880
1881 // Invalid buffer.
1882 errno = 0;
1883 ASSERT_EQ(nullptr, open_memstream(nullptr, &size));
1884 ASSERT_EQ(EINVAL, errno);
1885
1886 // Invalid size.
1887 errno = 0;
1888 ASSERT_EQ(nullptr, open_memstream(&p, nullptr));
1889 ASSERT_EQ(EINVAL, errno);
1890#else
Elliott Hughes9677fab2016-01-25 15:50:59 -08001891 GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
Elliott Hughes6b841db2014-08-20 16:10:49 -07001892#endif
1893}
Elliott Hughes31165ed2014-09-23 17:34:29 -07001894
Christopher Ferris13f26a72016-01-13 13:47:58 -08001895TEST(STDIO_TEST, fdopen_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07001896 int fd = open("/proc/version", O_RDONLY);
1897 ASSERT_TRUE(fd != -1);
1898
1899 // This fd doesn't have O_CLOEXEC...
Elliott Hughesa7f12942017-12-15 13:55:53 -08001900 AssertCloseOnExec(fd, false);
Elliott Hughes31165ed2014-09-23 17:34:29 -07001901
1902 FILE* fp = fdopen(fd, "re");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001903 ASSERT_TRUE(fp != nullptr);
Elliott Hughes31165ed2014-09-23 17:34:29 -07001904
1905 // ...but the new one does.
Elliott Hughesa7f12942017-12-15 13:55:53 -08001906 AssertCloseOnExec(fileno(fp), true);
Elliott Hughes31165ed2014-09-23 17:34:29 -07001907
1908 fclose(fp);
Elliott Hughes31165ed2014-09-23 17:34:29 -07001909}
1910
Christopher Ferris13f26a72016-01-13 13:47:58 -08001911TEST(STDIO_TEST, freopen_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07001912 FILE* fp = fopen("/proc/version", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001913 ASSERT_TRUE(fp != nullptr);
Elliott Hughes31165ed2014-09-23 17:34:29 -07001914
1915 // This FILE* doesn't have O_CLOEXEC...
Elliott Hughesa7f12942017-12-15 13:55:53 -08001916 AssertCloseOnExec(fileno(fp), false);
Elliott Hughes31165ed2014-09-23 17:34:29 -07001917
1918 fp = freopen("/proc/version", "re", fp);
1919
1920 // ...but the new one does.
Elliott Hughesa7f12942017-12-15 13:55:53 -08001921 AssertCloseOnExec(fileno(fp), true);
Elliott Hughes31165ed2014-09-23 17:34:29 -07001922
1923 fclose(fp);
1924}
Elliott Hughes20841a12014-12-01 16:13:30 -08001925
Elliott Hughesf226ee52016-02-03 11:24:28 -08001926TEST(STDIO_TEST, fopen64_freopen64) {
1927 FILE* fp = fopen64("/proc/version", "r");
1928 ASSERT_TRUE(fp != nullptr);
1929 fp = freopen64("/proc/version", "re", fp);
1930 ASSERT_TRUE(fp != nullptr);
1931 fclose(fp);
1932}
1933
Elliott Hughes20841a12014-12-01 16:13:30 -08001934// https://code.google.com/p/android/issues/detail?id=81155
1935// http://b/18556607
Christopher Ferris13f26a72016-01-13 13:47:58 -08001936TEST(STDIO_TEST, fread_unbuffered_pathological_performance) {
Elliott Hughes20841a12014-12-01 16:13:30 -08001937 FILE* fp = fopen("/dev/zero", "r");
Yi Kong32bc0fc2018-08-02 17:31:13 -07001938 ASSERT_TRUE(fp != nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08001939
1940 // Make this stream unbuffered.
Yi Kong32bc0fc2018-08-02 17:31:13 -07001941 setvbuf(fp, nullptr, _IONBF, 0);
Elliott Hughes20841a12014-12-01 16:13:30 -08001942
1943 char buf[65*1024];
1944 memset(buf, 0xff, sizeof(buf));
1945
Yi Kong32bc0fc2018-08-02 17:31:13 -07001946 time_t t0 = time(nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08001947 for (size_t i = 0; i < 1024; ++i) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001948 ASSERT_EQ(1U, fread(buf, 64*1024, 1, fp));
Elliott Hughes20841a12014-12-01 16:13:30 -08001949 }
Yi Kong32bc0fc2018-08-02 17:31:13 -07001950 time_t t1 = time(nullptr);
Elliott Hughes20841a12014-12-01 16:13:30 -08001951
1952 fclose(fp);
1953
1954 // 1024 64KiB reads should have been very quick.
1955 ASSERT_LE(t1 - t0, 1);
1956
1957 for (size_t i = 0; i < 64*1024; ++i) {
1958 ASSERT_EQ('\0', buf[i]);
1959 }
1960 for (size_t i = 64*1024; i < 65*1024; ++i) {
1961 ASSERT_EQ('\xff', buf[i]);
1962 }
1963}
Elliott Hughes75b99382015-01-20 11:23:50 -08001964
Christopher Ferris13f26a72016-01-13 13:47:58 -08001965TEST(STDIO_TEST, fread_EOF) {
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001966 std::string digits("0123456789");
1967 FILE* fp = fmemopen(&digits[0], digits.size(), "r");
Elliott Hughes75b99382015-01-20 11:23:50 -08001968
1969 // Try to read too much, but little enough that it still fits in the FILE's internal buffer.
1970 char buf1[4 * 4];
1971 memset(buf1, 0, sizeof(buf1));
1972 ASSERT_EQ(2U, fread(buf1, 4, 4, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001973 ASSERT_STREQ("0123456789", buf1);
Elliott Hughes75b99382015-01-20 11:23:50 -08001974 ASSERT_TRUE(feof(fp));
1975
1976 rewind(fp);
1977
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001978 // Try to read way too much so stdio tries to read more direct from the stream.
1979 char buf2[4 * 4096];
Elliott Hughes75b99382015-01-20 11:23:50 -08001980 memset(buf2, 0, sizeof(buf2));
1981 ASSERT_EQ(2U, fread(buf2, 4, 4096, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001982 ASSERT_STREQ("0123456789", buf2);
Elliott Hughes75b99382015-01-20 11:23:50 -08001983 ASSERT_TRUE(feof(fp));
1984
1985 fclose(fp);
1986}
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001987
1988static void test_fread_from_write_only_stream(size_t n) {
1989 FILE* fp = fopen("/dev/null", "w");
1990 std::vector<char> buf(n, 0);
1991 errno = 0;
1992 ASSERT_EQ(0U, fread(&buf[0], n, 1, fp));
1993 ASSERT_EQ(EBADF, errno);
1994 ASSERT_TRUE(ferror(fp));
1995 ASSERT_FALSE(feof(fp));
1996 fclose(fp);
1997}
1998
Christopher Ferris13f26a72016-01-13 13:47:58 -08001999TEST(STDIO_TEST, fread_from_write_only_stream_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002000 test_fread_from_write_only_stream(1);
2001}
2002
Christopher Ferris13f26a72016-01-13 13:47:58 -08002003TEST(STDIO_TEST, fread_from_write_only_stream_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002004 test_fread_from_write_only_stream(64*1024);
2005}
2006
2007static void test_fwrite_after_fread(size_t n) {
2008 TemporaryFile tf;
2009
2010 FILE* fp = fdopen(tf.fd, "w+");
2011 ASSERT_EQ(1U, fwrite("1", 1, 1, fp));
2012 fflush(fp);
2013
2014 // We've flushed but not rewound, so there's nothing to read.
2015 std::vector<char> buf(n, 0);
2016 ASSERT_EQ(0U, fread(&buf[0], 1, buf.size(), fp));
2017 ASSERT_TRUE(feof(fp));
2018
2019 // But hitting EOF doesn't prevent us from writing...
2020 errno = 0;
Elliott Hughes9677fab2016-01-25 15:50:59 -08002021 ASSERT_EQ(1U, fwrite("2", 1, 1, fp)) << strerror(errno);
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002022
2023 // And if we rewind, everything's there.
2024 rewind(fp);
2025 ASSERT_EQ(2U, fread(&buf[0], 1, buf.size(), fp));
2026 ASSERT_EQ('1', buf[0]);
2027 ASSERT_EQ('2', buf[1]);
2028
2029 fclose(fp);
2030}
2031
Christopher Ferris13f26a72016-01-13 13:47:58 -08002032TEST(STDIO_TEST, fwrite_after_fread_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002033 test_fwrite_after_fread(16);
2034}
2035
Christopher Ferris13f26a72016-01-13 13:47:58 -08002036TEST(STDIO_TEST, fwrite_after_fread_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08002037 test_fwrite_after_fread(64*1024);
2038}
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002039
2040// http://b/19172514
Christopher Ferris13f26a72016-01-13 13:47:58 -08002041TEST(STDIO_TEST, fread_after_fseek) {
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002042 TemporaryFile tf;
2043
2044 FILE* fp = fopen(tf.filename, "w+");
2045 ASSERT_TRUE(fp != nullptr);
2046
2047 char file_data[12288];
2048 for (size_t i = 0; i < 12288; i++) {
2049 file_data[i] = i;
2050 }
2051 ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp));
2052 fclose(fp);
2053
2054 fp = fopen(tf.filename, "r");
2055 ASSERT_TRUE(fp != nullptr);
2056
2057 char buffer[8192];
2058 size_t cur_location = 0;
2059 // Small read to populate internal buffer.
2060 ASSERT_EQ(100U, fread(buffer, 1, 100, fp));
2061 ASSERT_EQ(memcmp(file_data, buffer, 100), 0);
2062
2063 cur_location = static_cast<size_t>(ftell(fp));
2064 // Large read to force reading into the user supplied buffer and bypassing
2065 // the internal buffer.
2066 ASSERT_EQ(8192U, fread(buffer, 1, 8192, fp));
2067 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 8192), 0);
2068
2069 // Small backwards seek to verify fseek does not reuse the internal buffer.
Elliott Hughes9677fab2016-01-25 15:50:59 -08002070 ASSERT_EQ(0, fseek(fp, -22, SEEK_CUR)) << strerror(errno);
Christopher Ferriscc9ca102015-02-27 18:22:45 -08002071 cur_location = static_cast<size_t>(ftell(fp));
2072 ASSERT_EQ(22U, fread(buffer, 1, 22, fp));
2073 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 22), 0);
2074
2075 fclose(fp);
2076}
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002077
2078// https://code.google.com/p/android/issues/detail?id=184847
Christopher Ferris13f26a72016-01-13 13:47:58 -08002079TEST(STDIO_TEST, fread_EOF_184847) {
Elliott Hughes8ab433d2015-10-09 17:57:26 -07002080 TemporaryFile tf;
2081 char buf[6] = {0};
2082
2083 FILE* fw = fopen(tf.filename, "w");
2084 ASSERT_TRUE(fw != nullptr);
2085
2086 FILE* fr = fopen(tf.filename, "r");
2087 ASSERT_TRUE(fr != nullptr);
2088
2089 fwrite("a", 1, 1, fw);
2090 fflush(fw);
2091 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
2092 ASSERT_STREQ("a", buf);
2093
2094 // 'fr' is now at EOF.
2095 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
2096 ASSERT_TRUE(feof(fr));
2097
2098 // Write some more...
2099 fwrite("z", 1, 1, fw);
2100 fflush(fw);
2101
2102 // ...and check that we can read it back.
2103 // (BSD thinks that once a stream has hit EOF, it must always return EOF. SysV disagrees.)
2104 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
2105 ASSERT_STREQ("z", buf);
2106
2107 // But now we're done.
2108 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
2109
2110 fclose(fr);
2111 fclose(fw);
2112}
Elliott Hughes923f1652016-01-19 15:46:05 -08002113
2114TEST(STDIO_TEST, fclose_invalidates_fd) {
2115 // The typical error we're trying to help people catch involves accessing
2116 // memory after it's been freed. But we know that stdin/stdout/stderr are
2117 // special and don't get deallocated, so this test uses stdin.
2118 ASSERT_EQ(0, fclose(stdin));
2119
2120 // Even though using a FILE* after close is undefined behavior, I've closed
2121 // this bug as "WAI" too many times. We shouldn't hand out stale fds,
2122 // especially because they might actually correspond to a real stream.
2123 errno = 0;
2124 ASSERT_EQ(-1, fileno(stdin));
2125 ASSERT_EQ(EBADF, errno);
2126}
Elliott Hughes2704bd12016-01-20 17:14:53 -08002127
2128TEST(STDIO_TEST, fseek_ftell_unseekable) {
2129#if defined(__BIONIC__) // glibc has fopencookie instead.
2130 auto read_fn = [](void*, char*, int) { return -1; };
2131 FILE* fp = funopen(nullptr, read_fn, nullptr, nullptr, nullptr);
2132 ASSERT_TRUE(fp != nullptr);
2133
2134 // Check that ftell balks on an unseekable FILE*.
2135 errno = 0;
2136 ASSERT_EQ(-1, ftell(fp));
2137 ASSERT_EQ(ESPIPE, errno);
2138
2139 // SEEK_CUR is rewritten as SEEK_SET internally...
2140 errno = 0;
2141 ASSERT_EQ(-1, fseek(fp, 0, SEEK_CUR));
2142 ASSERT_EQ(ESPIPE, errno);
2143
2144 // ...so it's worth testing the direct seek path too.
2145 errno = 0;
2146 ASSERT_EQ(-1, fseek(fp, 0, SEEK_SET));
2147 ASSERT_EQ(ESPIPE, errno);
2148
2149 fclose(fp);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002150#else
2151 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
2152#endif
2153}
2154
2155TEST(STDIO_TEST, funopen_EINVAL) {
2156#if defined(__BIONIC__)
2157 errno = 0;
2158 ASSERT_EQ(nullptr, funopen(nullptr, nullptr, nullptr, nullptr, nullptr));
2159 ASSERT_EQ(EINVAL, errno);
2160#else
2161 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
2162#endif
2163}
2164
2165TEST(STDIO_TEST, funopen_seek) {
2166#if defined(__BIONIC__)
2167 auto read_fn = [](void*, char*, int) { return -1; };
2168
2169 auto seek_fn = [](void*, fpos_t, int) -> fpos_t { return 0xfedcba12; };
2170 auto seek64_fn = [](void*, fpos64_t, int) -> fpos64_t { return 0xfedcba12345678; };
2171
2172 FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr);
2173 ASSERT_TRUE(fp != nullptr);
2174 fpos_t pos;
Elliott Hughes955426e2016-01-26 18:25:52 -08002175#if defined(__LP64__)
2176 EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno);
2177 EXPECT_EQ(0xfedcba12LL, pos);
2178#else
2179 EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno);
2180 EXPECT_EQ(EOVERFLOW, errno);
2181#endif
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002182
2183 FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr);
2184 ASSERT_TRUE(fp64 != nullptr);
2185 fpos64_t pos64;
Elliott Hughes955426e2016-01-26 18:25:52 -08002186 EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno);
2187 EXPECT_EQ(0xfedcba12345678, pos64);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08002188#else
2189 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
Elliott Hughes2704bd12016-01-20 17:14:53 -08002190#endif
2191}
Elliott Hughes71288cb2016-01-22 19:22:44 -08002192
2193TEST(STDIO_TEST, lots_of_concurrent_files) {
2194 std::vector<TemporaryFile*> tfs;
2195 std::vector<FILE*> fps;
2196
2197 for (size_t i = 0; i < 256; ++i) {
2198 TemporaryFile* tf = new TemporaryFile;
2199 tfs.push_back(tf);
2200 FILE* fp = fopen(tf->filename, "w+");
2201 fps.push_back(fp);
2202 fprintf(fp, "hello %zu!\n", i);
2203 fflush(fp);
2204 }
2205
2206 for (size_t i = 0; i < 256; ++i) {
Elliott Hughes71288cb2016-01-22 19:22:44 -08002207 char expected[BUFSIZ];
2208 snprintf(expected, sizeof(expected), "hello %zu!\n", i);
Elliott Hughes71288cb2016-01-22 19:22:44 -08002209
Elliott Hughes70715da2016-08-01 16:35:17 -07002210 AssertFileIs(fps[i], expected);
Elliott Hughes71288cb2016-01-22 19:22:44 -08002211 fclose(fps[i]);
2212 delete tfs[i];
2213 }
2214}
Elliott Hughes9677fab2016-01-25 15:50:59 -08002215
2216static void AssertFileOffsetAt(FILE* fp, off64_t offset) {
2217 EXPECT_EQ(offset, ftell(fp));
2218 EXPECT_EQ(offset, ftello(fp));
Elliott Hughese4fa6e92016-02-02 22:39:15 -08002219 EXPECT_EQ(offset, ftello64(fp));
Elliott Hughes9677fab2016-01-25 15:50:59 -08002220 fpos_t pos;
2221 fpos64_t pos64;
2222 EXPECT_EQ(0, fgetpos(fp, &pos));
2223 EXPECT_EQ(0, fgetpos64(fp, &pos64));
2224#if defined(__BIONIC__)
2225 EXPECT_EQ(offset, static_cast<off64_t>(pos));
2226 EXPECT_EQ(offset, static_cast<off64_t>(pos64));
2227#else
2228 GTEST_LOG_(INFO) << "glibc's fpos_t is opaque.\n";
2229#endif
2230}
2231
2232TEST(STDIO_TEST, seek_tell_family_smoke) {
2233 TemporaryFile tf;
2234 FILE* fp = fdopen(tf.fd, "w+");
2235
2236 // Initially we should be at 0.
2237 AssertFileOffsetAt(fp, 0);
2238
2239 // Seek to offset 8192.
2240 ASSERT_EQ(0, fseek(fp, 8192, SEEK_SET));
2241 AssertFileOffsetAt(fp, 8192);
2242 fpos_t eight_k_pos;
2243 ASSERT_EQ(0, fgetpos(fp, &eight_k_pos));
2244
2245 // Seek forward another 8192...
2246 ASSERT_EQ(0, fseek(fp, 8192, SEEK_CUR));
2247 AssertFileOffsetAt(fp, 8192 + 8192);
2248 fpos64_t sixteen_k_pos64;
2249 ASSERT_EQ(0, fgetpos64(fp, &sixteen_k_pos64));
2250
2251 // Seek back 8192...
2252 ASSERT_EQ(0, fseek(fp, -8192, SEEK_CUR));
2253 AssertFileOffsetAt(fp, 8192);
2254
2255 // Since we haven't written anything, the end is also at 0.
2256 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2257 AssertFileOffsetAt(fp, 0);
2258
2259 // Check that our fpos64_t from 16KiB works...
2260 ASSERT_EQ(0, fsetpos64(fp, &sixteen_k_pos64));
2261 AssertFileOffsetAt(fp, 8192 + 8192);
2262 // ...as does our fpos_t from 8192.
2263 ASSERT_EQ(0, fsetpos(fp, &eight_k_pos));
2264 AssertFileOffsetAt(fp, 8192);
2265
2266 // Do fseeko and fseeko64 work too?
2267 ASSERT_EQ(0, fseeko(fp, 1234, SEEK_SET));
2268 AssertFileOffsetAt(fp, 1234);
2269 ASSERT_EQ(0, fseeko64(fp, 5678, SEEK_SET));
2270 AssertFileOffsetAt(fp, 5678);
2271
2272 fclose(fp);
2273}
2274
2275TEST(STDIO_TEST, fseek_fseeko_EINVAL) {
2276 TemporaryFile tf;
2277 FILE* fp = fdopen(tf.fd, "w+");
2278
2279 // Bad whence.
2280 errno = 0;
2281 ASSERT_EQ(-1, fseek(fp, 0, 123));
2282 ASSERT_EQ(EINVAL, errno);
2283 errno = 0;
2284 ASSERT_EQ(-1, fseeko(fp, 0, 123));
2285 ASSERT_EQ(EINVAL, errno);
2286 errno = 0;
2287 ASSERT_EQ(-1, fseeko64(fp, 0, 123));
2288 ASSERT_EQ(EINVAL, errno);
2289
2290 // Bad offset.
2291 errno = 0;
2292 ASSERT_EQ(-1, fseek(fp, -1, SEEK_SET));
2293 ASSERT_EQ(EINVAL, errno);
2294 errno = 0;
2295 ASSERT_EQ(-1, fseeko(fp, -1, SEEK_SET));
2296 ASSERT_EQ(EINVAL, errno);
2297 errno = 0;
2298 ASSERT_EQ(-1, fseeko64(fp, -1, SEEK_SET));
2299 ASSERT_EQ(EINVAL, errno);
2300
2301 fclose(fp);
2302}
Elliott Hughes20788ae2016-06-09 15:16:32 -07002303
2304TEST(STDIO_TEST, ctermid) {
2305 ASSERT_STREQ("/dev/tty", ctermid(nullptr));
2306
2307 char buf[L_ctermid] = {};
2308 ASSERT_EQ(buf, ctermid(buf));
2309 ASSERT_STREQ("/dev/tty", buf);
2310}
Elliott Hughesd1f25a72016-08-05 15:53:03 -07002311
2312TEST(STDIO_TEST, remove) {
2313 struct stat sb;
2314
2315 TemporaryFile tf;
2316 ASSERT_EQ(0, remove(tf.filename));
2317 ASSERT_EQ(-1, lstat(tf.filename, &sb));
2318 ASSERT_EQ(ENOENT, errno);
2319
2320 TemporaryDir td;
2321 ASSERT_EQ(0, remove(td.dirname));
2322 ASSERT_EQ(-1, lstat(td.dirname, &sb));
2323 ASSERT_EQ(ENOENT, errno);
2324
2325 errno = 0;
2326 ASSERT_EQ(-1, remove(tf.filename));
2327 ASSERT_EQ(ENOENT, errno);
2328
2329 errno = 0;
2330 ASSERT_EQ(-1, remove(td.dirname));
2331 ASSERT_EQ(ENOENT, errno);
2332}
Elliott Hughesfb3873d2016-08-10 11:07:54 -07002333
2334TEST(STDIO_DEATHTEST, snprintf_30445072_known_buffer_size) {
2335 char buf[16];
2336 ASSERT_EXIT(snprintf(buf, atol("-1"), "hello"),
2337 testing::KilledBySignal(SIGABRT),
2338#if defined(NOFORTIFY)
2339 "FORTIFY: vsnprintf: size .* > SSIZE_MAX"
2340#else
2341 "FORTIFY: vsnprintf: prevented .*-byte write into 16-byte buffer"
2342#endif
2343 );
2344}
2345
2346TEST(STDIO_DEATHTEST, snprintf_30445072_unknown_buffer_size) {
2347 std::string buf = "world";
2348 ASSERT_EXIT(snprintf(&buf[0], atol("-1"), "hello"),
2349 testing::KilledBySignal(SIGABRT),
2350 "FORTIFY: vsnprintf: size .* > SSIZE_MAX");
2351}
2352
2353TEST(STDIO_TEST, sprintf_30445072) {
2354 std::string buf = "world";
2355 sprintf(&buf[0], "hello");
2356 ASSERT_EQ(buf, "hello");
2357}
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002358
Elliott Hughes654cd832018-08-30 16:00:42 -07002359TEST(STDIO_TEST, printf_m) {
2360 char buf[BUFSIZ];
2361 errno = 0;
2362 snprintf(buf, sizeof(buf), "<%m>");
2363 ASSERT_STREQ("<Success>", buf);
2364 errno = -1;
2365 snprintf(buf, sizeof(buf), "<%m>");
2366 ASSERT_STREQ("<Unknown error -1>", buf);
2367 errno = EINVAL;
2368 snprintf(buf, sizeof(buf), "<%m>");
2369 ASSERT_STREQ("<Invalid argument>", buf);
2370}
2371
2372TEST(STDIO_TEST, wprintf_m) {
2373 wchar_t buf[BUFSIZ];
2374 errno = 0;
2375 swprintf(buf, sizeof(buf), L"<%m>");
2376 ASSERT_EQ(std::wstring(L"<Success>"), buf);
2377 errno = -1;
2378 swprintf(buf, sizeof(buf), L"<%m>");
2379 ASSERT_EQ(std::wstring(L"<Unknown error -1>"), buf);
2380 errno = EINVAL;
2381 swprintf(buf, sizeof(buf), L"<%m>");
2382 ASSERT_EQ(std::wstring(L"<Invalid argument>"), buf);
2383}
2384
Elliott Hughes33a8cb12017-07-25 18:06:46 -07002385TEST(STDIO_TEST, fopen_append_mode_and_ftell) {
2386 TemporaryFile tf;
2387 SetFileTo(tf.filename, "0123456789");
2388 FILE* fp = fopen(tf.filename, "a");
2389 EXPECT_EQ(10, ftell(fp));
2390 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2391 EXPECT_EQ(2, ftell(fp));
2392 ASSERT_NE(EOF, fputs("xxx", fp));
2393 ASSERT_EQ(0, fflush(fp));
2394 EXPECT_EQ(13, ftell(fp));
2395 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2396 EXPECT_EQ(13, ftell(fp));
2397 ASSERT_EQ(0, fclose(fp));
2398 AssertFileIs(tf.filename, "0123456789xxx");
2399}
2400
2401TEST(STDIO_TEST, fdopen_append_mode_and_ftell) {
2402 TemporaryFile tf;
2403 SetFileTo(tf.filename, "0123456789");
2404 int fd = open(tf.filename, O_RDWR);
2405 ASSERT_NE(-1, fd);
2406 // POSIX: "The file position indicator associated with the new stream is set to the position
2407 // indicated by the file offset associated with the file descriptor."
2408 ASSERT_EQ(4, lseek(fd, 4, SEEK_SET));
2409 FILE* fp = fdopen(fd, "a");
2410 EXPECT_EQ(4, ftell(fp));
2411 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2412 EXPECT_EQ(2, ftell(fp));
2413 ASSERT_NE(EOF, fputs("xxx", fp));
2414 ASSERT_EQ(0, fflush(fp));
2415 EXPECT_EQ(13, ftell(fp));
2416 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2417 EXPECT_EQ(13, ftell(fp));
2418 ASSERT_EQ(0, fclose(fp));
2419 AssertFileIs(tf.filename, "0123456789xxx");
2420}
2421
2422TEST(STDIO_TEST, freopen_append_mode_and_ftell) {
2423 TemporaryFile tf;
2424 SetFileTo(tf.filename, "0123456789");
2425 FILE* other_fp = fopen("/proc/version", "r");
2426 FILE* fp = freopen(tf.filename, "a", other_fp);
2427 EXPECT_EQ(10, ftell(fp));
2428 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
2429 EXPECT_EQ(2, ftell(fp));
2430 ASSERT_NE(EOF, fputs("xxx", fp));
2431 ASSERT_EQ(0, fflush(fp));
2432 EXPECT_EQ(13, ftell(fp));
2433 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2434 EXPECT_EQ(13, ftell(fp));
2435 ASSERT_EQ(0, fclose(fp));
2436 AssertFileIs(tf.filename, "0123456789xxx");
2437}
Elliott Hughesb15feb72017-07-31 17:20:18 -07002438
2439TEST(STDIO_TEST, constants) {
2440 ASSERT_LE(FILENAME_MAX, PATH_MAX);
2441 ASSERT_EQ(L_tmpnam, PATH_MAX);
2442}
Elliott Hughes37ad9592017-10-30 17:47:12 -07002443
2444TEST(STDIO_TEST, perror) {
2445 ExecTestHelper eth;
2446 eth.Run([&]() { errno = EINVAL; perror("a b c"); exit(0); }, 0, "a b c: Invalid argument\n");
2447 eth.Run([&]() { errno = EINVAL; perror(nullptr); exit(0); }, 0, "Invalid argument\n");
2448 eth.Run([&]() { errno = EINVAL; perror(""); exit(0); }, 0, "Invalid argument\n");
2449}
2450
2451TEST(STDIO_TEST, puts) {
2452 ExecTestHelper eth;
2453 eth.Run([&]() { exit(puts("a b c")); }, 0, "a b c\n");
2454}
2455
2456TEST(STDIO_TEST, unlocked) {
2457 TemporaryFile tf;
2458
2459 FILE* fp = fopen(tf.filename, "w+");
2460 ASSERT_TRUE(fp != nullptr);
2461
2462 clearerr_unlocked(fp);
2463 ASSERT_FALSE(feof_unlocked(fp));
2464 ASSERT_FALSE(ferror_unlocked(fp));
2465
2466 ASSERT_EQ(fileno(fp), fileno_unlocked(fp));
2467
2468 ASSERT_NE(EOF, putc_unlocked('a', fp));
2469 ASSERT_NE(EOF, putc('b', fp));
2470 ASSERT_NE(EOF, fputc_unlocked('c', fp));
2471 ASSERT_NE(EOF, fputc('d', fp));
2472
2473 rewind(fp);
2474 ASSERT_EQ('a', getc_unlocked(fp));
2475 ASSERT_EQ('b', getc(fp));
2476 ASSERT_EQ('c', fgetc_unlocked(fp));
2477 ASSERT_EQ('d', fgetc(fp));
2478
2479 rewind(fp);
2480 ASSERT_EQ(2U, fwrite_unlocked("AB", 1, 2, fp));
2481 ASSERT_EQ(2U, fwrite("CD", 1, 2, fp));
2482 ASSERT_EQ(0, fflush_unlocked(fp));
2483
2484 rewind(fp);
2485 char buf[BUFSIZ] = {};
2486 ASSERT_EQ(2U, fread_unlocked(&buf[0], 1, 2, fp));
2487 ASSERT_EQ(2U, fread(&buf[2], 1, 2, fp));
2488 ASSERT_STREQ("ABCD", buf);
2489
2490 rewind(fp);
2491 ASSERT_NE(EOF, fputs("hello ", fp));
2492 ASSERT_NE(EOF, fputs_unlocked("world", fp));
2493 ASSERT_NE(EOF, fputc('\n', fp));
2494
2495 rewind(fp);
2496 ASSERT_TRUE(fgets_unlocked(buf, sizeof(buf), fp) != nullptr);
2497 ASSERT_STREQ("hello world\n", buf);
2498
2499 ASSERT_EQ(0, fclose(fp));
2500}
Ryan Prichardbf549862017-11-07 15:30:32 -08002501
2502TEST(STDIO_TEST, fseek_64bit) {
2503 TemporaryFile tf;
2504 FILE* fp = fopen64(tf.filename, "w+");
2505 ASSERT_TRUE(fp != nullptr);
2506 ASSERT_EQ(0, fseeko64(fp, 0x2'0000'0000, SEEK_SET));
2507 ASSERT_EQ(0x2'0000'0000, ftello64(fp));
2508 ASSERT_EQ(0, fseeko64(fp, 0x1'0000'0000, SEEK_CUR));
2509 ASSERT_EQ(0x3'0000'0000, ftello64(fp));
2510 ASSERT_EQ(0, fclose(fp));
2511}
2512
2513// POSIX requires that fseek/fseeko fail with EOVERFLOW if the new file offset
2514// isn't representable in long/off_t.
2515TEST(STDIO_TEST, fseek_overflow_32bit) {
2516 TemporaryFile tf;
2517 FILE* fp = fopen64(tf.filename, "w+");
2518 ASSERT_EQ(0, ftruncate64(fileno(fp), 0x2'0000'0000));
2519
2520 // Bionic implements overflow checking for SEEK_CUR, but glibc doesn't.
2521#if defined(__BIONIC__) && !defined(__LP64__)
2522 ASSERT_EQ(0, fseek(fp, 0x7fff'ffff, SEEK_SET));
2523 ASSERT_EQ(-1, fseek(fp, 1, SEEK_CUR));
2524 ASSERT_EQ(EOVERFLOW, errno);
2525#endif
2526
2527 // Neither Bionic nor glibc implement the overflow checking for SEEK_END.
2528 // (Aside: FreeBSD's libc is an example of a libc that checks both SEEK_CUR
2529 // and SEEK_END -- many C libraries check neither.)
2530 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
2531 ASSERT_EQ(0x2'0000'0000, ftello64(fp));
2532
2533 fclose(fp);
2534}
Elliott Hughesf1a38382018-08-22 15:38:07 -07002535
2536TEST(STDIO_TEST, dev_std_files) {
2537 // POSIX only mentions /dev/stdout, but we should have all three (http://b/31824379).
2538 char path[PATH_MAX];
Christopher Ferris2c4ec7e2018-08-23 11:17:55 -07002539 ssize_t length = readlink("/dev/stdin", path, sizeof(path));
2540 ASSERT_LT(0, length);
2541 ASSERT_EQ("/proc/self/fd/0", std::string(path, length));
2542
2543 length = readlink("/dev/stdout", path, sizeof(path));
2544 ASSERT_LT(0, length);
2545 ASSERT_EQ("/proc/self/fd/1", std::string(path, length));
2546
2547 length = readlink("/dev/stderr", path, sizeof(path));
2548 ASSERT_LT(0, length);
2549 ASSERT_EQ("/proc/self/fd/2", std::string(path, length));
Elliott Hughesf1a38382018-08-22 15:38:07 -07002550}