blob: 63da9e0408fca8e94184285eee25014528e8de03 [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>
25#include <sys/stat.h>
26#include <unistd.h>
Elliott Hughes05493712014-04-17 17:30:03 -070027#include <wchar.h>
Calin Juravle03e4ebe2014-05-08 14:42:06 +010028#include <locale.h>
29
Elliott Hughese6bb5a22015-01-23 17:48:15 -080030#include <vector>
31
Elliott Hughesfb3873d2016-08-10 11:07:54 -070032#include "BionicDeathTest.h"
Calin Juravle03e4ebe2014-05-08 14:42:06 +010033#include "TemporaryFile.h"
Elliott Hughes91875dc2012-09-24 17:55:15 -070034
Christopher Ferris13f26a72016-01-13 13:47:58 -080035#if defined(NOFORTIFY)
36#define STDIO_TEST stdio_nofortify
Elliott Hughesfb3873d2016-08-10 11:07:54 -070037#define STDIO_DEATHTEST stdio_nofortify_DeathTest
Christopher Ferris13f26a72016-01-13 13:47:58 -080038#else
39#define STDIO_TEST stdio
Elliott Hughesfb3873d2016-08-10 11:07:54 -070040#define STDIO_DEATHTEST stdio_DeathTest
Christopher Ferris13f26a72016-01-13 13:47:58 -080041#endif
42
Elliott Hughesfb3873d2016-08-10 11:07:54 -070043class stdio_DeathTest : public BionicDeathTest {};
44class stdio_nofortify_DeathTest : public BionicDeathTest {};
45
Elliott Hughes70715da2016-08-01 16:35:17 -070046static void AssertFileIs(FILE* fp, const char* expected, bool is_fmemopen = false) {
47 rewind(fp);
48
49 char line[1024];
50 ASSERT_EQ(line, fgets(line, sizeof(line), fp));
51 ASSERT_STREQ(expected, line);
52
53 if (is_fmemopen) {
54 // fmemopen appends a trailing NUL byte, which probably shouldn't show up as an
55 // extra empty line, but does on every C library I tested...
56 ASSERT_EQ(line, fgets(line, sizeof(line), fp));
57 ASSERT_STREQ("", line);
58 }
59
60 // Make sure there isn't anything else in the file.
61 ASSERT_EQ(nullptr, fgets(line, sizeof(line), fp)) << "junk at end of file: " << line;
62}
63
Christopher Ferris13f26a72016-01-13 13:47:58 -080064TEST(STDIO_TEST, flockfile_18208568_stderr) {
Elliott Hughes6a03abc2014-11-03 12:32:17 -080065 // Check that we have a _recursive_ mutex for flockfile.
66 flockfile(stderr);
67 feof(stderr); // We don't care about the result, but this needs to take the lock.
68 funlockfile(stderr);
69}
70
Christopher Ferris13f26a72016-01-13 13:47:58 -080071TEST(STDIO_TEST, flockfile_18208568_regular) {
Elliott Hughes6a03abc2014-11-03 12:32:17 -080072 // We never had a bug for streams other than stdin/stdout/stderr, but test anyway.
73 FILE* fp = fopen("/dev/null", "w");
74 ASSERT_TRUE(fp != NULL);
75 flockfile(fp);
76 feof(fp);
77 funlockfile(fp);
78 fclose(fp);
79}
80
Christopher Ferris13f26a72016-01-13 13:47:58 -080081TEST(STDIO_TEST, tmpfile_fileno_fprintf_rewind_fgets) {
Elliott Hughes91875dc2012-09-24 17:55:15 -070082 FILE* fp = tmpfile();
83 ASSERT_TRUE(fp != NULL);
84
85 int fd = fileno(fp);
86 ASSERT_NE(fd, -1);
87
88 struct stat sb;
89 int rc = fstat(fd, &sb);
90 ASSERT_NE(rc, -1);
91 ASSERT_EQ(sb.st_mode & 0777, 0600U);
92
93 rc = fprintf(fp, "hello\n");
94 ASSERT_EQ(rc, 6);
95
Elliott Hughes70715da2016-08-01 16:35:17 -070096 AssertFileIs(fp, "hello\n");
Elliott Hughes91875dc2012-09-24 17:55:15 -070097 fclose(fp);
98}
Irina Tirdeaeac9eb42012-09-08 09:28:30 +030099
Elliott Hughesf226ee52016-02-03 11:24:28 -0800100TEST(STDIO_TEST, tmpfile64) {
101 FILE* fp = tmpfile64();
102 ASSERT_TRUE(fp != nullptr);
103 fclose(fp);
104}
105
Christopher Ferris13f26a72016-01-13 13:47:58 -0800106TEST(STDIO_TEST, dprintf) {
Calin Juravle6afb2a92014-05-22 11:47:47 +0100107 TemporaryFile tf;
108
109 int rc = dprintf(tf.fd, "hello\n");
110 ASSERT_EQ(rc, 6);
111
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800112 lseek(tf.fd, 0, SEEK_SET);
Christopher Ferris9e01ea62014-05-29 12:49:35 -0700113 FILE* tfile = fdopen(tf.fd, "r");
114 ASSERT_TRUE(tfile != NULL);
Calin Juravle6afb2a92014-05-22 11:47:47 +0100115
Elliott Hughes70715da2016-08-01 16:35:17 -0700116 AssertFileIs(tfile, "hello\n");
Christopher Ferris9e01ea62014-05-29 12:49:35 -0700117 fclose(tfile);
Calin Juravle6afb2a92014-05-22 11:47:47 +0100118}
119
Christopher Ferris13f26a72016-01-13 13:47:58 -0800120TEST(STDIO_TEST, getdelim) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300121 FILE* fp = tmpfile();
122 ASSERT_TRUE(fp != NULL);
123
124 const char* line_written = "This is a test";
125 int rc = fprintf(fp, "%s", line_written);
126 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
127
128 rewind(fp);
129
130 char* word_read = NULL;
131 size_t allocated_length = 0;
132
133 const char* expected[] = { "This ", " ", "is ", "a ", "test" };
134 for (size_t i = 0; i < 5; ++i) {
135 ASSERT_FALSE(feof(fp));
136 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i])));
137 ASSERT_GE(allocated_length, strlen(expected[i]));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800138 ASSERT_STREQ(expected[i], word_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300139 }
140 // The last read should have set the end-of-file indicator for the stream.
141 ASSERT_TRUE(feof(fp));
142 clearerr(fp);
143
144 // getdelim returns -1 but doesn't set errno if we're already at EOF.
145 // It should set the end-of-file indicator for the stream, though.
146 errno = 0;
147 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800148 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300149 ASSERT_TRUE(feof(fp));
150
151 free(word_read);
152 fclose(fp);
153}
154
Christopher Ferris13f26a72016-01-13 13:47:58 -0800155TEST(STDIO_TEST, getdelim_invalid) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300156 FILE* fp = tmpfile();
Elliott Hughes6ad8f762013-12-19 14:56:17 -0800157 ASSERT_TRUE(fp != NULL);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300158
159 char* buffer = NULL;
160 size_t buffer_length = 0;
161
162 // The first argument can't be NULL.
163 errno = 0;
164 ASSERT_EQ(getdelim(NULL, &buffer_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800165 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300166
167 // The second argument can't be NULL.
168 errno = 0;
169 ASSERT_EQ(getdelim(&buffer, NULL, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800170 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300171
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700172 // The underlying fd can't be closed.
173 ASSERT_EQ(0, close(fileno(fp)));
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300174 errno = 0;
175 ASSERT_EQ(getdelim(&buffer, &buffer_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800176 ASSERT_EQ(EBADF, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700177 fclose(fp);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300178}
179
Christopher Ferris13f26a72016-01-13 13:47:58 -0800180TEST(STDIO_TEST, getdelim_directory) {
Elliott Hughes694fd2d2015-04-05 10:51:56 -0700181 FILE* fp = fopen("/proc", "r");
182 ASSERT_TRUE(fp != NULL);
183 char* word_read;
184 size_t allocated_length;
185 ASSERT_EQ(-1, getdelim(&word_read, &allocated_length, ' ', fp));
186 fclose(fp);
187}
188
Christopher Ferris13f26a72016-01-13 13:47:58 -0800189TEST(STDIO_TEST, getline) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300190 FILE* fp = tmpfile();
191 ASSERT_TRUE(fp != NULL);
192
193 const char* line_written = "This is a test for getline\n";
194 const size_t line_count = 5;
195
196 for (size_t i = 0; i < line_count; ++i) {
197 int rc = fprintf(fp, "%s", line_written);
198 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
199 }
200
201 rewind(fp);
202
203 char* line_read = NULL;
204 size_t allocated_length = 0;
205
206 size_t read_line_count = 0;
207 ssize_t read_char_count;
208 while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) {
209 ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written)));
210 ASSERT_GE(allocated_length, strlen(line_written));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800211 ASSERT_STREQ(line_written, line_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300212 ++read_line_count;
213 }
214 ASSERT_EQ(read_line_count, line_count);
215
216 // The last read should have set the end-of-file indicator for the stream.
217 ASSERT_TRUE(feof(fp));
218 clearerr(fp);
219
220 // getline returns -1 but doesn't set errno if we're already at EOF.
221 // It should set the end-of-file indicator for the stream, though.
222 errno = 0;
223 ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800224 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300225 ASSERT_TRUE(feof(fp));
226
227 free(line_read);
228 fclose(fp);
229}
230
Christopher Ferris13f26a72016-01-13 13:47:58 -0800231TEST(STDIO_TEST, getline_invalid) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300232 FILE* fp = tmpfile();
Elliott Hughes6ad8f762013-12-19 14:56:17 -0800233 ASSERT_TRUE(fp != NULL);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300234
235 char* buffer = NULL;
236 size_t buffer_length = 0;
237
238 // The first argument can't be NULL.
239 errno = 0;
240 ASSERT_EQ(getline(NULL, &buffer_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800241 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300242
243 // The second argument can't be NULL.
244 errno = 0;
245 ASSERT_EQ(getline(&buffer, NULL, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800246 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300247
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700248 // The underlying fd can't be closed.
249 ASSERT_EQ(0, close(fileno(fp)));
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300250 errno = 0;
251 ASSERT_EQ(getline(&buffer, &buffer_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800252 ASSERT_EQ(EBADF, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700253 fclose(fp);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300254}
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000255
Christopher Ferris13f26a72016-01-13 13:47:58 -0800256TEST(STDIO_TEST, printf_ssize_t) {
Elliott Hughese2556422013-02-28 10:51:14 -0800257 // http://b/8253769
Elliott Hughese2556422013-02-28 10:51:14 -0800258 ASSERT_EQ(sizeof(ssize_t), sizeof(long int));
Elliott Hughesb6e22482013-03-08 15:28:52 -0800259 ASSERT_EQ(sizeof(ssize_t), sizeof(size_t));
260 // For our 32-bit ABI, we had a ssize_t definition that confuses GCC into saying:
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000261 // error: format '%zd' expects argument of type 'signed size_t',
262 // but argument 4 has type 'ssize_t {aka long int}' [-Werror=format]
263 ssize_t v = 1;
264 char buf[32];
265 snprintf(buf, sizeof(buf), "%zd", v);
266}
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800267
Elliott Hughes05493712014-04-17 17:30:03 -0700268// https://code.google.com/p/android/issues/detail?id=64886
Christopher Ferris13f26a72016-01-13 13:47:58 -0800269TEST(STDIO_TEST, snprintf_a) {
Elliott Hughes05493712014-04-17 17:30:03 -0700270 char buf[BUFSIZ];
271 EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235));
272 EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf);
273}
274
Christopher Ferris13f26a72016-01-13 13:47:58 -0800275TEST(STDIO_TEST, snprintf_lc) {
Elliott Hughes05493712014-04-17 17:30:03 -0700276 char buf[BUFSIZ];
277 wint_t wc = L'a';
278 EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc));
279 EXPECT_STREQ("<a>", buf);
280}
281
Christopher Ferris13f26a72016-01-13 13:47:58 -0800282TEST(STDIO_TEST, snprintf_ls) {
Elliott Hughes05493712014-04-17 17:30:03 -0700283 char buf[BUFSIZ];
284 wchar_t* ws = NULL;
285 EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws));
286 EXPECT_STREQ("<(null)>", buf);
287
288 wchar_t chars[] = { L'h', L'i', 0 };
289 ws = chars;
290 EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws));
291 EXPECT_STREQ("<hi>", buf);
292}
293
Christopher Ferris13f26a72016-01-13 13:47:58 -0800294TEST(STDIO_TEST, snprintf_n) {
Elliott Hughes063525c2014-05-13 11:19:57 -0700295#if defined(__BIONIC__)
Elliott Hughese2341d02014-05-02 18:16:32 -0700296 // http://b/14492135
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700297 char buf[32];
Elliott Hughese2341d02014-05-02 18:16:32 -0700298 int i = 1234;
299 EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
300 EXPECT_EQ(1234, i);
301 EXPECT_STREQ("a n b", buf);
302#else
Elliott Hughes9677fab2016-01-25 15:50:59 -0800303 GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
Elliott Hughese2341d02014-05-02 18:16:32 -0700304#endif
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700305}
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700306
Christopher Ferris13f26a72016-01-13 13:47:58 -0800307TEST(STDIO_TEST, snprintf_smoke) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700308 char buf[BUFSIZ];
309
310 snprintf(buf, sizeof(buf), "a");
311 EXPECT_STREQ("a", buf);
312
313 snprintf(buf, sizeof(buf), "%%");
314 EXPECT_STREQ("%", buf);
315
316 snprintf(buf, sizeof(buf), "01234");
317 EXPECT_STREQ("01234", buf);
318
319 snprintf(buf, sizeof(buf), "a%sb", "01234");
320 EXPECT_STREQ("a01234b", buf);
321
322 char* s = NULL;
323 snprintf(buf, sizeof(buf), "a%sb", s);
324 EXPECT_STREQ("a(null)b", buf);
325
326 snprintf(buf, sizeof(buf), "aa%scc", "bb");
327 EXPECT_STREQ("aabbcc", buf);
328
329 snprintf(buf, sizeof(buf), "a%cc", 'b');
330 EXPECT_STREQ("abc", buf);
331
332 snprintf(buf, sizeof(buf), "a%db", 1234);
333 EXPECT_STREQ("a1234b", buf);
334
335 snprintf(buf, sizeof(buf), "a%db", -8123);
336 EXPECT_STREQ("a-8123b", buf);
337
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700338 snprintf(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010));
Elliott Hughes1d13c642013-09-23 16:02:39 -0700339 EXPECT_STREQ("a16b", buf);
340
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700341 snprintf(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
Elliott Hughes1d13c642013-09-23 16:02:39 -0700342 EXPECT_STREQ("a16b", buf);
343
344 snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
345 EXPECT_STREQ("a68719476736b", buf);
346
347 snprintf(buf, sizeof(buf), "a%ldb", 70000L);
348 EXPECT_STREQ("a70000b", buf);
349
350 snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
351 EXPECT_STREQ("a0xb0001234b", buf);
352
353 snprintf(buf, sizeof(buf), "a%xz", 0x12ab);
354 EXPECT_STREQ("a12abz", buf);
355
356 snprintf(buf, sizeof(buf), "a%Xz", 0x12ab);
357 EXPECT_STREQ("a12ABz", buf);
358
359 snprintf(buf, sizeof(buf), "a%08xz", 0x123456);
360 EXPECT_STREQ("a00123456z", buf);
361
362 snprintf(buf, sizeof(buf), "a%5dz", 1234);
363 EXPECT_STREQ("a 1234z", buf);
364
365 snprintf(buf, sizeof(buf), "a%05dz", 1234);
366 EXPECT_STREQ("a01234z", buf);
367
368 snprintf(buf, sizeof(buf), "a%8dz", 1234);
369 EXPECT_STREQ("a 1234z", buf);
370
371 snprintf(buf, sizeof(buf), "a%-8dz", 1234);
372 EXPECT_STREQ("a1234 z", buf);
373
374 snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef");
375 EXPECT_STREQ("Aabcdef Z", buf);
376
377 snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
378 EXPECT_STREQ("Ahello:1234Z", buf);
379
380 snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
381 EXPECT_STREQ("a005:5:05z", buf);
382
383 void* p = NULL;
384 snprintf(buf, sizeof(buf), "a%d,%pz", 5, p);
Christopher Ferris13613132013-10-28 15:24:04 -0700385#if defined(__BIONIC__)
Elliott Hughes1d13c642013-09-23 16:02:39 -0700386 EXPECT_STREQ("a5,0x0z", buf);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800387#else // __BIONIC__
Christopher Ferris13613132013-10-28 15:24:04 -0700388 EXPECT_STREQ("a5,(nil)z", buf);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800389#endif // __BIONIC__
Elliott Hughes1d13c642013-09-23 16:02:39 -0700390
391 snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
392 EXPECT_STREQ("a68719476736,6,7,8z", buf);
393
394 snprintf(buf, sizeof(buf), "a_%f_b", 1.23f);
395 EXPECT_STREQ("a_1.230000_b", buf);
396
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700397 snprintf(buf, sizeof(buf), "a_%g_b", 3.14);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700398 EXPECT_STREQ("a_3.14_b", buf);
Alexander Ivchenkoedd7c2e2014-04-01 17:01:39 +0400399
400 snprintf(buf, sizeof(buf), "%1$s %1$s", "print_me_twice");
401 EXPECT_STREQ("print_me_twice print_me_twice", buf);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700402}
403
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800404template <typename T>
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700405static void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...),
406 int sscanf_fn(const T*, const T*, ...),
407 const T* fmt_string, const T* fmt, const T* fmt_plus,
408 const T* minus_inf, const T* inf_, const T* plus_inf,
409 const T* minus_nan, const T* nan_, const T* plus_nan) {
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800410 T buf[BUFSIZ];
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700411 float f;
Elliott Hughes7823f322014-04-14 12:11:28 -0700412
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700413 // NaN.
414
415 snprintf_fn(buf, sizeof(buf), fmt, nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800416 EXPECT_STREQ(nan_, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700417 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
418 EXPECT_TRUE(isnan(f));
419
420 snprintf_fn(buf, sizeof(buf), fmt, -nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800421 EXPECT_STREQ(minus_nan, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700422 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
423 EXPECT_TRUE(isnan(f));
424
425 snprintf_fn(buf, sizeof(buf), fmt_plus, nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800426 EXPECT_STREQ(plus_nan, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700427 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
428 EXPECT_TRUE(isnan(f));
429
430 snprintf_fn(buf, sizeof(buf), fmt_plus, -nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800431 EXPECT_STREQ(minus_nan, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700432 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
433 EXPECT_TRUE(isnan(f));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800434
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700435 // Inf.
436
437 snprintf_fn(buf, sizeof(buf), fmt, HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800438 EXPECT_STREQ(inf_, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700439 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
440 EXPECT_EQ(HUGE_VALF, f);
441
442 snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800443 EXPECT_STREQ(minus_inf, buf) << fmt;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700444 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
445 EXPECT_EQ(-HUGE_VALF, f);
446
447 snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800448 EXPECT_STREQ(plus_inf, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700449 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
450 EXPECT_EQ(HUGE_VALF, f);
451
452 snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800453 EXPECT_STREQ(minus_inf, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700454 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
455 EXPECT_EQ(-HUGE_VALF, f);
456
457 // Check case-insensitivity.
458 snprintf_fn(buf, sizeof(buf), fmt_string, "[InFiNiTy]");
459 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f)) << buf;
460 EXPECT_EQ(HUGE_VALF, f);
461 snprintf_fn(buf, sizeof(buf), fmt_string, "[NaN]");
462 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f)) << buf;
463 EXPECT_TRUE(isnan(f));
Elliott Hughes7823f322014-04-14 12:11:28 -0700464}
465
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700466TEST(STDIO_TEST, snprintf_sscanf_inf_nan) {
467 CheckInfNan(snprintf, sscanf, "%s",
468 "[%a]", "[%+a]",
469 "[-inf]", "[inf]", "[+inf]",
470 "[-nan]", "[nan]", "[+nan]");
471 CheckInfNan(snprintf, sscanf, "%s",
472 "[%A]", "[%+A]",
473 "[-INF]", "[INF]", "[+INF]",
474 "[-NAN]", "[NAN]", "[+NAN]");
475 CheckInfNan(snprintf, sscanf, "%s",
476 "[%e]", "[%+e]",
477 "[-inf]", "[inf]", "[+inf]",
478 "[-nan]", "[nan]", "[+nan]");
479 CheckInfNan(snprintf, sscanf, "%s",
480 "[%E]", "[%+E]",
481 "[-INF]", "[INF]", "[+INF]",
482 "[-NAN]", "[NAN]", "[+NAN]");
483 CheckInfNan(snprintf, sscanf, "%s",
484 "[%f]", "[%+f]",
485 "[-inf]", "[inf]", "[+inf]",
486 "[-nan]", "[nan]", "[+nan]");
487 CheckInfNan(snprintf, sscanf, "%s",
488 "[%F]", "[%+F]",
489 "[-INF]", "[INF]", "[+INF]",
490 "[-NAN]", "[NAN]", "[+NAN]");
491 CheckInfNan(snprintf, sscanf, "%s",
492 "[%g]", "[%+g]",
493 "[-inf]", "[inf]", "[+inf]",
494 "[-nan]", "[nan]", "[+nan]");
495 CheckInfNan(snprintf, sscanf, "%s",
496 "[%G]", "[%+G]",
497 "[-INF]", "[INF]", "[+INF]",
498 "[-NAN]", "[NAN]", "[+NAN]");
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800499}
Elliott Hughes7823f322014-04-14 12:11:28 -0700500
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700501TEST(STDIO_TEST, swprintf_swscanf_inf_nan) {
502 CheckInfNan(swprintf, swscanf, L"%s",
503 L"[%a]", L"[%+a]",
504 L"[-inf]", L"[inf]", L"[+inf]",
505 L"[-nan]", L"[nan]", L"[+nan]");
506 CheckInfNan(swprintf, swscanf, L"%s",
507 L"[%A]", L"[%+A]",
508 L"[-INF]", L"[INF]", L"[+INF]",
509 L"[-NAN]", L"[NAN]", L"[+NAN]");
510 CheckInfNan(swprintf, swscanf, L"%s",
511 L"[%e]", L"[%+e]",
512 L"[-inf]", L"[inf]", L"[+inf]",
513 L"[-nan]", L"[nan]", L"[+nan]");
514 CheckInfNan(swprintf, swscanf, L"%s",
515 L"[%E]", L"[%+E]",
516 L"[-INF]", L"[INF]", L"[+INF]",
517 L"[-NAN]", L"[NAN]", L"[+NAN]");
518 CheckInfNan(swprintf, swscanf, L"%s",
519 L"[%f]", L"[%+f]",
520 L"[-inf]", L"[inf]", L"[+inf]",
521 L"[-nan]", L"[nan]", L"[+nan]");
522 CheckInfNan(swprintf, swscanf, L"%s",
523 L"[%F]", L"[%+F]",
524 L"[-INF]", L"[INF]", L"[+INF]",
525 L"[-NAN]", L"[NAN]", L"[+NAN]");
526 CheckInfNan(swprintf, swscanf, L"%s",
527 L"[%g]", L"[%+g]",
528 L"[-inf]", L"[inf]", L"[+inf]",
529 L"[-nan]", L"[nan]", L"[+nan]");
530 CheckInfNan(swprintf, swscanf, L"%s",
531 L"[%G]", L"[%+G]",
532 L"[-INF]", L"[INF]", L"[+INF]",
533 L"[-NAN]", L"[NAN]", L"[+NAN]");
Elliott Hughes7823f322014-04-14 12:11:28 -0700534}
535
Christopher Ferris13f26a72016-01-13 13:47:58 -0800536TEST(STDIO_TEST, snprintf_d_INT_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700537 char buf[BUFSIZ];
538 snprintf(buf, sizeof(buf), "%d", INT_MAX);
539 EXPECT_STREQ("2147483647", buf);
540}
541
Christopher Ferris13f26a72016-01-13 13:47:58 -0800542TEST(STDIO_TEST, snprintf_d_INT_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700543 char buf[BUFSIZ];
544 snprintf(buf, sizeof(buf), "%d", INT_MIN);
545 EXPECT_STREQ("-2147483648", buf);
546}
547
Christopher Ferris13f26a72016-01-13 13:47:58 -0800548TEST(STDIO_TEST, snprintf_ld_LONG_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700549 char buf[BUFSIZ];
550 snprintf(buf, sizeof(buf), "%ld", LONG_MAX);
Josh Gaob36efa42016-09-15 13:55:41 -0700551#if defined(__LP64__)
Elliott Hughes925753a2013-10-18 13:17:18 -0700552 EXPECT_STREQ("9223372036854775807", buf);
553#else
Elliott Hughes1d13c642013-09-23 16:02:39 -0700554 EXPECT_STREQ("2147483647", buf);
Elliott Hughes925753a2013-10-18 13:17:18 -0700555#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700556}
557
Christopher Ferris13f26a72016-01-13 13:47:58 -0800558TEST(STDIO_TEST, snprintf_ld_LONG_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700559 char buf[BUFSIZ];
560 snprintf(buf, sizeof(buf), "%ld", LONG_MIN);
Josh Gaob36efa42016-09-15 13:55:41 -0700561#if defined(__LP64__)
Elliott Hughes925753a2013-10-18 13:17:18 -0700562 EXPECT_STREQ("-9223372036854775808", buf);
563#else
Elliott Hughes1d13c642013-09-23 16:02:39 -0700564 EXPECT_STREQ("-2147483648", buf);
Elliott Hughes925753a2013-10-18 13:17:18 -0700565#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700566}
567
Christopher Ferris13f26a72016-01-13 13:47:58 -0800568TEST(STDIO_TEST, snprintf_lld_LLONG_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700569 char buf[BUFSIZ];
570 snprintf(buf, sizeof(buf), "%lld", LLONG_MAX);
571 EXPECT_STREQ("9223372036854775807", buf);
572}
573
Christopher Ferris13f26a72016-01-13 13:47:58 -0800574TEST(STDIO_TEST, snprintf_lld_LLONG_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700575 char buf[BUFSIZ];
576 snprintf(buf, sizeof(buf), "%lld", LLONG_MIN);
577 EXPECT_STREQ("-9223372036854775808", buf);
578}
579
Christopher Ferris13f26a72016-01-13 13:47:58 -0800580TEST(STDIO_TEST, snprintf_e) {
Elliott Hughes4bd97ce2014-04-10 17:48:14 -0700581 char buf[BUFSIZ];
582
583 snprintf(buf, sizeof(buf), "%e", 1.5);
584 EXPECT_STREQ("1.500000e+00", buf);
585
586 snprintf(buf, sizeof(buf), "%Le", 1.5l);
587 EXPECT_STREQ("1.500000e+00", buf);
588}
589
Christopher Ferris13f26a72016-01-13 13:47:58 -0800590TEST(STDIO_TEST, snprintf_negative_zero_5084292) {
Elliott Hughese77f38f2014-05-14 12:39:12 -0700591 char buf[BUFSIZ];
592
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800593 snprintf(buf, sizeof(buf), "%e", -0.0);
594 EXPECT_STREQ("-0.000000e+00", buf);
595 snprintf(buf, sizeof(buf), "%E", -0.0);
596 EXPECT_STREQ("-0.000000E+00", buf);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700597 snprintf(buf, sizeof(buf), "%f", -0.0);
598 EXPECT_STREQ("-0.000000", buf);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800599 snprintf(buf, sizeof(buf), "%F", -0.0);
600 EXPECT_STREQ("-0.000000", buf);
601 snprintf(buf, sizeof(buf), "%g", -0.0);
602 EXPECT_STREQ("-0", buf);
603 snprintf(buf, sizeof(buf), "%G", -0.0);
604 EXPECT_STREQ("-0", buf);
605 snprintf(buf, sizeof(buf), "%a", -0.0);
606 EXPECT_STREQ("-0x0p+0", buf);
607 snprintf(buf, sizeof(buf), "%A", -0.0);
608 EXPECT_STREQ("-0X0P+0", buf);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700609}
610
Christopher Ferris13f26a72016-01-13 13:47:58 -0800611TEST(STDIO_TEST, snprintf_utf8_15439554) {
Dan Albert1aec7c12014-07-30 10:53:48 -0700612 locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0);
Wally Yaua40fdbd2014-08-26 09:47:23 -0700613 locale_t old_locale = uselocale(cloc);
Dan Albert1aec7c12014-07-30 10:53:48 -0700614
Elliott Hughes69f05d22014-06-05 20:10:09 -0700615 // http://b/15439554
616 char buf[BUFSIZ];
617
618 // 1-byte character.
619 snprintf(buf, sizeof(buf), "%dx%d", 1, 2);
620 EXPECT_STREQ("1x2", buf);
621 // 2-byte character.
622 snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2);
623 EXPECT_STREQ("1¢2", buf);
624 // 3-byte character.
625 snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2);
626 EXPECT_STREQ("1€2", buf);
627 // 4-byte character.
628 snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2);
629 EXPECT_STREQ("1𤭢2", buf);
Dan Albert1aec7c12014-07-30 10:53:48 -0700630
Wally Yaua40fdbd2014-08-26 09:47:23 -0700631 uselocale(old_locale);
Dan Albert1aec7c12014-07-30 10:53:48 -0700632 freelocale(cloc);
Elliott Hughes69f05d22014-06-05 20:10:09 -0700633}
634
Elliott Hughes43f7c872016-02-05 11:18:41 -0800635static void* snprintf_small_stack_fn(void*) {
636 // Make life (realistically) hard for ourselves by allocating our own buffer for the result.
637 char buf[PATH_MAX];
638 snprintf(buf, sizeof(buf), "/proc/%d", getpid());
639 return nullptr;
640}
641
642TEST(STDIO_TEST, snprintf_small_stack) {
643 // Is it safe to call snprintf on a thread with a small stack?
644 // (The snprintf implementation puts some pretty large buffers on the stack.)
645 pthread_attr_t a;
646 ASSERT_EQ(0, pthread_attr_init(&a));
647 ASSERT_EQ(0, pthread_attr_setstacksize(&a, PTHREAD_STACK_MIN));
648
649 pthread_t t;
650 ASSERT_EQ(0, pthread_create(&t, &a, snprintf_small_stack_fn, nullptr));
651 ASSERT_EQ(0, pthread_join(t, nullptr));
652}
653
Elliott Hughes8200e552016-02-05 21:57:37 -0800654TEST(STDIO_TEST, snprintf_asterisk_overflow) {
655 char buf[128];
656 ASSERT_EQ(5, snprintf(buf, sizeof(buf), "%.*s%c", 4, "hello world", '!'));
657 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX/2, "hello world", '!'));
658 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX-1, "hello world", '!'));
659 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX, "hello world", '!'));
660 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", -1, "hello world", '!'));
661
662 // INT_MAX-1, INT_MAX, INT_MAX+1.
663 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483646s%c", "hello world", '!'));
664 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483647s%c", "hello world", '!'));
665 ASSERT_EQ(-1, snprintf(buf, sizeof(buf), "%.2147483648s%c", "hello world", '!'));
666 ASSERT_EQ(ENOMEM, errno);
667}
668
Elliott Hughes70715da2016-08-01 16:35:17 -0700669TEST(STDIO_TEST, fprintf) {
670 TemporaryFile tf;
671
672 FILE* tfile = fdopen(tf.fd, "r+");
673 ASSERT_TRUE(tfile != nullptr);
674
675 ASSERT_EQ(7, fprintf(tfile, "%d %s", 123, "abc"));
676 AssertFileIs(tfile, "123 abc");
677 fclose(tfile);
678}
679
Christopher Ferris13f26a72016-01-13 13:47:58 -0800680TEST(STDIO_TEST, fprintf_failures_7229520) {
Elliott Hughes69f05d22014-06-05 20:10:09 -0700681 // http://b/7229520
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700682 FILE* fp;
683
684 // Unbuffered case where the fprintf(3) itself fails.
685 ASSERT_NE(nullptr, fp = tmpfile());
686 setbuf(fp, NULL);
687 ASSERT_EQ(4, fprintf(fp, "epic"));
688 ASSERT_EQ(0, close(fileno(fp)));
689 ASSERT_EQ(-1, fprintf(fp, "fail"));
690 ASSERT_EQ(-1, fclose(fp));
691
692 // Buffered case where we won't notice until the fclose(3).
693 // It's likely this is what was actually seen in http://b/7229520,
694 // and that expecting fprintf to fail is setting yourself up for
695 // disappointment. Remember to check fclose(3)'s return value, kids!
696 ASSERT_NE(nullptr, fp = tmpfile());
697 ASSERT_EQ(4, fprintf(fp, "epic"));
698 ASSERT_EQ(0, close(fileno(fp)));
699 ASSERT_EQ(4, fprintf(fp, "fail"));
700 ASSERT_EQ(-1, fclose(fp));
701}
702
Christopher Ferris13f26a72016-01-13 13:47:58 -0800703TEST(STDIO_TEST, popen) {
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800704 FILE* fp = popen("cat /proc/version", "r");
705 ASSERT_TRUE(fp != NULL);
706
707 char buf[16];
708 char* s = fgets(buf, sizeof(buf), fp);
709 buf[13] = '\0';
710 ASSERT_STREQ("Linux version", s);
711
712 ASSERT_EQ(0, pclose(fp));
713}
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700714
Christopher Ferris13f26a72016-01-13 13:47:58 -0800715TEST(STDIO_TEST, getc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700716 FILE* fp = fopen("/proc/version", "r");
717 ASSERT_TRUE(fp != NULL);
718 ASSERT_EQ('L', getc(fp));
719 ASSERT_EQ('i', getc(fp));
720 ASSERT_EQ('n', getc(fp));
721 ASSERT_EQ('u', getc(fp));
722 ASSERT_EQ('x', getc(fp));
723 fclose(fp);
724}
725
Christopher Ferris13f26a72016-01-13 13:47:58 -0800726TEST(STDIO_TEST, putc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700727 FILE* fp = fopen("/proc/version", "r");
728 ASSERT_TRUE(fp != NULL);
729 ASSERT_EQ(EOF, putc('x', fp));
730 fclose(fp);
731}
Elliott Hughes603332f2014-03-12 17:10:41 -0700732
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700733TEST(STDIO_TEST, sscanf_swscanf) {
734 struct stuff {
735 char s1[123];
736 int i1;
737 double d1;
738 float f1;
739 char s2[123];
740
741 void Check() {
742 ASSERT_STREQ("hello", s1);
743 ASSERT_EQ(123, i1);
744 ASSERT_DOUBLE_EQ(1.23, d1);
745 ASSERT_FLOAT_EQ(9.0f, f1);
746 ASSERT_STREQ("world", s2);
747 }
748 } s;
749
750 memset(&s, 0, sizeof(s));
751 ASSERT_EQ(5, sscanf(" hello 123 1.23 0x1.2p3 world",
752 "%s %i %lf %f %s",
753 s.s1, &s.i1, &s.d1, &s.f1, s.s2));
754 s.Check();
755
756 memset(&s, 0, sizeof(s));
757 ASSERT_EQ(5, swscanf(L" hello 123 1.23 0x1.2p3 world",
758 L"%s %i %lf %f %s",
759 s.s1, &s.i1, &s.d1, &s.f1, s.s2));
760 s.Check();
Elliott Hughes603332f2014-03-12 17:10:41 -0700761}
Elliott Hughes53b24382014-05-02 18:29:25 -0700762
Christopher Ferris13f26a72016-01-13 13:47:58 -0800763TEST(STDIO_TEST, cantwrite_EBADF) {
Elliott Hughes53b24382014-05-02 18:29:25 -0700764 // If we open a file read-only...
765 FILE* fp = fopen("/proc/version", "r");
766
767 // ...all attempts to write to that file should return failure.
768
769 // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
770 // glibc gets the wide-character functions wrong.
771
772 errno = 0;
773 EXPECT_EQ(EOF, putc('x', fp));
774 EXPECT_EQ(EBADF, errno);
775
776 errno = 0;
777 EXPECT_EQ(EOF, fprintf(fp, "hello"));
778 EXPECT_EQ(EBADF, errno);
779
780 errno = 0;
781 EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
Elliott Hughes063525c2014-05-13 11:19:57 -0700782#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -0700783 EXPECT_EQ(EBADF, errno);
784#endif
785
786 errno = 0;
Elliott Hughes53b24382014-05-02 18:29:25 -0700787 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
788 EXPECT_EQ(EBADF, errno);
789
790 errno = 0;
791 EXPECT_EQ(EOF, fputs("hello", fp));
792 EXPECT_EQ(EBADF, errno);
793
794 errno = 0;
795 EXPECT_EQ(WEOF, fputwc(L'x', fp));
Elliott Hughes063525c2014-05-13 11:19:57 -0700796#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -0700797 EXPECT_EQ(EBADF, errno);
798#endif
799}
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100800
801// Tests that we can only have a consistent and correct fpos_t when using
802// f*pos functions (i.e. fpos doesn't get inside a multi byte character).
Christopher Ferris13f26a72016-01-13 13:47:58 -0800803TEST(STDIO_TEST, consistent_fpos_t) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100804 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
805 uselocale(LC_GLOBAL_LOCALE);
806
807 FILE* fp = tmpfile();
808 ASSERT_TRUE(fp != NULL);
809
810 wchar_t mb_one_bytes = L'h';
811 wchar_t mb_two_bytes = 0x00a2;
812 wchar_t mb_three_bytes = 0x20ac;
813 wchar_t mb_four_bytes = 0x24b62;
814
815 // Write to file.
816 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp)));
817 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
818 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
819 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
820
821 rewind(fp);
822
823 // Record each character position.
824 fpos_t pos1;
825 fpos_t pos2;
826 fpos_t pos3;
827 fpos_t pos4;
828 fpos_t pos5;
829 EXPECT_EQ(0, fgetpos(fp, &pos1));
830 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
831 EXPECT_EQ(0, fgetpos(fp, &pos2));
832 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
833 EXPECT_EQ(0, fgetpos(fp, &pos3));
834 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
835 EXPECT_EQ(0, fgetpos(fp, &pos4));
836 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
837 EXPECT_EQ(0, fgetpos(fp, &pos5));
838
Elliott Hughes063525c2014-05-13 11:19:57 -0700839#if defined(__BIONIC__)
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100840 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD
841 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In
842 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE
843 // structure.
844 ASSERT_EQ(0, static_cast<off_t>(pos1));
845 ASSERT_EQ(1, static_cast<off_t>(pos2));
846 ASSERT_EQ(3, static_cast<off_t>(pos3));
847 ASSERT_EQ(6, static_cast<off_t>(pos4));
848 ASSERT_EQ(10, static_cast<off_t>(pos5));
849#endif
850
851 // Exercise back and forth movements of the position.
852 ASSERT_EQ(0, fsetpos(fp, &pos2));
853 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
854 ASSERT_EQ(0, fsetpos(fp, &pos1));
855 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
856 ASSERT_EQ(0, fsetpos(fp, &pos4));
857 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
858 ASSERT_EQ(0, fsetpos(fp, &pos3));
859 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
860 ASSERT_EQ(0, fsetpos(fp, &pos5));
861 ASSERT_EQ(WEOF, fgetwc(fp));
862
863 fclose(fp);
864}
865
866// Exercise the interaction between fpos and seek.
Christopher Ferris13f26a72016-01-13 13:47:58 -0800867TEST(STDIO_TEST, fpos_t_and_seek) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100868 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
869 uselocale(LC_GLOBAL_LOCALE);
870
Calin Juravle9b95ea92014-05-14 17:07:10 +0100871 // In glibc-2.16 fseek doesn't work properly in wide mode
872 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is
873 // to close and re-open the file. We do it in order to make the test pass
874 // with all glibcs.
875
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100876 TemporaryFile tf;
877 FILE* fp = fdopen(tf.fd, "w+");
878 ASSERT_TRUE(fp != NULL);
879
880 wchar_t mb_two_bytes = 0x00a2;
881 wchar_t mb_three_bytes = 0x20ac;
882 wchar_t mb_four_bytes = 0x24b62;
883
884 // Write to file.
885 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
886 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
887 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
888
889 fflush(fp);
890 fclose(fp);
891
892 fp = fopen(tf.filename, "r");
893 ASSERT_TRUE(fp != NULL);
894
895 // Store a valid position.
896 fpos_t mb_two_bytes_pos;
897 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos));
898
899 // Move inside mb_four_bytes with fseek.
900 long offset_inside_mb = 6;
901 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET));
902
903 // Store the "inside multi byte" position.
904 fpos_t pos_inside_mb;
905 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb));
Elliott Hughes063525c2014-05-13 11:19:57 -0700906#if defined(__BIONIC__)
907 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb));
908#endif
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100909
910 // Reading from within a byte should produce an error.
911 ASSERT_EQ(WEOF, fgetwc(fp));
912 ASSERT_EQ(EILSEQ, errno);
913
914 // Reverting to a valid position should work.
915 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos));
916 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
917
918 // Moving withing a multi byte with fsetpos should work but reading should
919 // produce an error.
920 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb));
921 ASSERT_EQ(WEOF, fgetwc(fp));
922 ASSERT_EQ(EILSEQ, errno);
923
924 fclose(fp);
925}
Elliott Hughes6b841db2014-08-20 16:10:49 -0700926
Christopher Ferris13f26a72016-01-13 13:47:58 -0800927TEST(STDIO_TEST, fmemopen) {
Elliott Hughes6b841db2014-08-20 16:10:49 -0700928 char buf[16];
929 memset(buf, 0, sizeof(buf));
930 FILE* fp = fmemopen(buf, sizeof(buf), "r+");
931 ASSERT_EQ('<', fputc('<', fp));
932 ASSERT_NE(EOF, fputs("abc>\n", fp));
933 fflush(fp);
934
935 ASSERT_STREQ("<abc>\n", buf);
936
Elliott Hughes70715da2016-08-01 16:35:17 -0700937 AssertFileIs(fp, "<abc>\n", true);
Elliott Hughes6b841db2014-08-20 16:10:49 -0700938 fclose(fp);
939}
940
Christopher Ferris13f26a72016-01-13 13:47:58 -0800941TEST(STDIO_TEST, fmemopen_NULL) {
Elliott Hughes6b841db2014-08-20 16:10:49 -0700942 FILE* fp = fmemopen(nullptr, 128, "r+");
943 ASSERT_NE(EOF, fputs("xyz\n", fp));
944
Elliott Hughes70715da2016-08-01 16:35:17 -0700945 AssertFileIs(fp, "xyz\n", true);
Elliott Hughes6b841db2014-08-20 16:10:49 -0700946 fclose(fp);
947}
948
Christopher Ferris13f26a72016-01-13 13:47:58 -0800949TEST(STDIO_TEST, fmemopen_EINVAL) {
Elliott Hughes6b841db2014-08-20 16:10:49 -0700950 char buf[16];
951
952 // Invalid size.
953 errno = 0;
954 ASSERT_EQ(nullptr, fmemopen(buf, 0, "r+"));
955 ASSERT_EQ(EINVAL, errno);
956
957 // No '+' with NULL buffer.
958 errno = 0;
959 ASSERT_EQ(nullptr, fmemopen(nullptr, 0, "r"));
960 ASSERT_EQ(EINVAL, errno);
961}
962
Christopher Ferris13f26a72016-01-13 13:47:58 -0800963TEST(STDIO_TEST, open_memstream) {
Elliott Hughes6b841db2014-08-20 16:10:49 -0700964 char* p = nullptr;
965 size_t size = 0;
966 FILE* fp = open_memstream(&p, &size);
967 ASSERT_NE(EOF, fputs("hello, world!", fp));
968 fclose(fp);
969
970 ASSERT_STREQ("hello, world!", p);
971 ASSERT_EQ(strlen("hello, world!"), size);
972 free(p);
973}
974
Christopher Ferris13f26a72016-01-13 13:47:58 -0800975TEST(STDIO_TEST, open_memstream_EINVAL) {
Elliott Hughes6b841db2014-08-20 16:10:49 -0700976#if defined(__BIONIC__)
977 char* p;
978 size_t size;
979
980 // Invalid buffer.
981 errno = 0;
982 ASSERT_EQ(nullptr, open_memstream(nullptr, &size));
983 ASSERT_EQ(EINVAL, errno);
984
985 // Invalid size.
986 errno = 0;
987 ASSERT_EQ(nullptr, open_memstream(&p, nullptr));
988 ASSERT_EQ(EINVAL, errno);
989#else
Elliott Hughes9677fab2016-01-25 15:50:59 -0800990 GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
Elliott Hughes6b841db2014-08-20 16:10:49 -0700991#endif
992}
Elliott Hughes31165ed2014-09-23 17:34:29 -0700993
Christopher Ferris13f26a72016-01-13 13:47:58 -0800994TEST(STDIO_TEST, fdopen_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -0700995 int fd = open("/proc/version", O_RDONLY);
996 ASSERT_TRUE(fd != -1);
997
998 // This fd doesn't have O_CLOEXEC...
999 int flags = fcntl(fd, F_GETFD);
1000 ASSERT_TRUE(flags != -1);
1001 ASSERT_EQ(0, flags & FD_CLOEXEC);
1002
1003 FILE* fp = fdopen(fd, "re");
1004 ASSERT_TRUE(fp != NULL);
1005
1006 // ...but the new one does.
1007 flags = fcntl(fileno(fp), F_GETFD);
1008 ASSERT_TRUE(flags != -1);
1009 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
1010
1011 fclose(fp);
1012 close(fd);
1013}
1014
Christopher Ferris13f26a72016-01-13 13:47:58 -08001015TEST(STDIO_TEST, freopen_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07001016 FILE* fp = fopen("/proc/version", "r");
1017 ASSERT_TRUE(fp != NULL);
1018
1019 // This FILE* doesn't have O_CLOEXEC...
1020 int flags = fcntl(fileno(fp), F_GETFD);
1021 ASSERT_TRUE(flags != -1);
1022 ASSERT_EQ(0, flags & FD_CLOEXEC);
1023
1024 fp = freopen("/proc/version", "re", fp);
1025
1026 // ...but the new one does.
1027 flags = fcntl(fileno(fp), F_GETFD);
1028 ASSERT_TRUE(flags != -1);
1029 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
1030
1031 fclose(fp);
1032}
Elliott Hughes20841a12014-12-01 16:13:30 -08001033
Elliott Hughesf226ee52016-02-03 11:24:28 -08001034TEST(STDIO_TEST, fopen64_freopen64) {
1035 FILE* fp = fopen64("/proc/version", "r");
1036 ASSERT_TRUE(fp != nullptr);
1037 fp = freopen64("/proc/version", "re", fp);
1038 ASSERT_TRUE(fp != nullptr);
1039 fclose(fp);
1040}
1041
Elliott Hughes20841a12014-12-01 16:13:30 -08001042// https://code.google.com/p/android/issues/detail?id=81155
1043// http://b/18556607
Christopher Ferris13f26a72016-01-13 13:47:58 -08001044TEST(STDIO_TEST, fread_unbuffered_pathological_performance) {
Elliott Hughes20841a12014-12-01 16:13:30 -08001045 FILE* fp = fopen("/dev/zero", "r");
1046 ASSERT_TRUE(fp != NULL);
1047
1048 // Make this stream unbuffered.
1049 setvbuf(fp, 0, _IONBF, 0);
1050
1051 char buf[65*1024];
1052 memset(buf, 0xff, sizeof(buf));
1053
1054 time_t t0 = time(NULL);
1055 for (size_t i = 0; i < 1024; ++i) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001056 ASSERT_EQ(1U, fread(buf, 64*1024, 1, fp));
Elliott Hughes20841a12014-12-01 16:13:30 -08001057 }
1058 time_t t1 = time(NULL);
1059
1060 fclose(fp);
1061
1062 // 1024 64KiB reads should have been very quick.
1063 ASSERT_LE(t1 - t0, 1);
1064
1065 for (size_t i = 0; i < 64*1024; ++i) {
1066 ASSERT_EQ('\0', buf[i]);
1067 }
1068 for (size_t i = 64*1024; i < 65*1024; ++i) {
1069 ASSERT_EQ('\xff', buf[i]);
1070 }
1071}
Elliott Hughes75b99382015-01-20 11:23:50 -08001072
Christopher Ferris13f26a72016-01-13 13:47:58 -08001073TEST(STDIO_TEST, fread_EOF) {
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001074 std::string digits("0123456789");
1075 FILE* fp = fmemopen(&digits[0], digits.size(), "r");
Elliott Hughes75b99382015-01-20 11:23:50 -08001076
1077 // Try to read too much, but little enough that it still fits in the FILE's internal buffer.
1078 char buf1[4 * 4];
1079 memset(buf1, 0, sizeof(buf1));
1080 ASSERT_EQ(2U, fread(buf1, 4, 4, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001081 ASSERT_STREQ("0123456789", buf1);
Elliott Hughes75b99382015-01-20 11:23:50 -08001082 ASSERT_TRUE(feof(fp));
1083
1084 rewind(fp);
1085
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001086 // Try to read way too much so stdio tries to read more direct from the stream.
1087 char buf2[4 * 4096];
Elliott Hughes75b99382015-01-20 11:23:50 -08001088 memset(buf2, 0, sizeof(buf2));
1089 ASSERT_EQ(2U, fread(buf2, 4, 4096, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001090 ASSERT_STREQ("0123456789", buf2);
Elliott Hughes75b99382015-01-20 11:23:50 -08001091 ASSERT_TRUE(feof(fp));
1092
1093 fclose(fp);
1094}
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001095
1096static void test_fread_from_write_only_stream(size_t n) {
1097 FILE* fp = fopen("/dev/null", "w");
1098 std::vector<char> buf(n, 0);
1099 errno = 0;
1100 ASSERT_EQ(0U, fread(&buf[0], n, 1, fp));
1101 ASSERT_EQ(EBADF, errno);
1102 ASSERT_TRUE(ferror(fp));
1103 ASSERT_FALSE(feof(fp));
1104 fclose(fp);
1105}
1106
Christopher Ferris13f26a72016-01-13 13:47:58 -08001107TEST(STDIO_TEST, fread_from_write_only_stream_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001108 test_fread_from_write_only_stream(1);
1109}
1110
Christopher Ferris13f26a72016-01-13 13:47:58 -08001111TEST(STDIO_TEST, fread_from_write_only_stream_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001112 test_fread_from_write_only_stream(64*1024);
1113}
1114
1115static void test_fwrite_after_fread(size_t n) {
1116 TemporaryFile tf;
1117
1118 FILE* fp = fdopen(tf.fd, "w+");
1119 ASSERT_EQ(1U, fwrite("1", 1, 1, fp));
1120 fflush(fp);
1121
1122 // We've flushed but not rewound, so there's nothing to read.
1123 std::vector<char> buf(n, 0);
1124 ASSERT_EQ(0U, fread(&buf[0], 1, buf.size(), fp));
1125 ASSERT_TRUE(feof(fp));
1126
1127 // But hitting EOF doesn't prevent us from writing...
1128 errno = 0;
Elliott Hughes9677fab2016-01-25 15:50:59 -08001129 ASSERT_EQ(1U, fwrite("2", 1, 1, fp)) << strerror(errno);
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001130
1131 // And if we rewind, everything's there.
1132 rewind(fp);
1133 ASSERT_EQ(2U, fread(&buf[0], 1, buf.size(), fp));
1134 ASSERT_EQ('1', buf[0]);
1135 ASSERT_EQ('2', buf[1]);
1136
1137 fclose(fp);
1138}
1139
Christopher Ferris13f26a72016-01-13 13:47:58 -08001140TEST(STDIO_TEST, fwrite_after_fread_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001141 test_fwrite_after_fread(16);
1142}
1143
Christopher Ferris13f26a72016-01-13 13:47:58 -08001144TEST(STDIO_TEST, fwrite_after_fread_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001145 test_fwrite_after_fread(64*1024);
1146}
Christopher Ferriscc9ca102015-02-27 18:22:45 -08001147
1148// http://b/19172514
Christopher Ferris13f26a72016-01-13 13:47:58 -08001149TEST(STDIO_TEST, fread_after_fseek) {
Christopher Ferriscc9ca102015-02-27 18:22:45 -08001150 TemporaryFile tf;
1151
1152 FILE* fp = fopen(tf.filename, "w+");
1153 ASSERT_TRUE(fp != nullptr);
1154
1155 char file_data[12288];
1156 for (size_t i = 0; i < 12288; i++) {
1157 file_data[i] = i;
1158 }
1159 ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp));
1160 fclose(fp);
1161
1162 fp = fopen(tf.filename, "r");
1163 ASSERT_TRUE(fp != nullptr);
1164
1165 char buffer[8192];
1166 size_t cur_location = 0;
1167 // Small read to populate internal buffer.
1168 ASSERT_EQ(100U, fread(buffer, 1, 100, fp));
1169 ASSERT_EQ(memcmp(file_data, buffer, 100), 0);
1170
1171 cur_location = static_cast<size_t>(ftell(fp));
1172 // Large read to force reading into the user supplied buffer and bypassing
1173 // the internal buffer.
1174 ASSERT_EQ(8192U, fread(buffer, 1, 8192, fp));
1175 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 8192), 0);
1176
1177 // Small backwards seek to verify fseek does not reuse the internal buffer.
Elliott Hughes9677fab2016-01-25 15:50:59 -08001178 ASSERT_EQ(0, fseek(fp, -22, SEEK_CUR)) << strerror(errno);
Christopher Ferriscc9ca102015-02-27 18:22:45 -08001179 cur_location = static_cast<size_t>(ftell(fp));
1180 ASSERT_EQ(22U, fread(buffer, 1, 22, fp));
1181 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 22), 0);
1182
1183 fclose(fp);
1184}
Elliott Hughes8ab433d2015-10-09 17:57:26 -07001185
1186// https://code.google.com/p/android/issues/detail?id=184847
Christopher Ferris13f26a72016-01-13 13:47:58 -08001187TEST(STDIO_TEST, fread_EOF_184847) {
Elliott Hughes8ab433d2015-10-09 17:57:26 -07001188 TemporaryFile tf;
1189 char buf[6] = {0};
1190
1191 FILE* fw = fopen(tf.filename, "w");
1192 ASSERT_TRUE(fw != nullptr);
1193
1194 FILE* fr = fopen(tf.filename, "r");
1195 ASSERT_TRUE(fr != nullptr);
1196
1197 fwrite("a", 1, 1, fw);
1198 fflush(fw);
1199 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
1200 ASSERT_STREQ("a", buf);
1201
1202 // 'fr' is now at EOF.
1203 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
1204 ASSERT_TRUE(feof(fr));
1205
1206 // Write some more...
1207 fwrite("z", 1, 1, fw);
1208 fflush(fw);
1209
1210 // ...and check that we can read it back.
1211 // (BSD thinks that once a stream has hit EOF, it must always return EOF. SysV disagrees.)
1212 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
1213 ASSERT_STREQ("z", buf);
1214
1215 // But now we're done.
1216 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
1217
1218 fclose(fr);
1219 fclose(fw);
1220}
Elliott Hughes923f1652016-01-19 15:46:05 -08001221
1222TEST(STDIO_TEST, fclose_invalidates_fd) {
1223 // The typical error we're trying to help people catch involves accessing
1224 // memory after it's been freed. But we know that stdin/stdout/stderr are
1225 // special and don't get deallocated, so this test uses stdin.
1226 ASSERT_EQ(0, fclose(stdin));
1227
1228 // Even though using a FILE* after close is undefined behavior, I've closed
1229 // this bug as "WAI" too many times. We shouldn't hand out stale fds,
1230 // especially because they might actually correspond to a real stream.
1231 errno = 0;
1232 ASSERT_EQ(-1, fileno(stdin));
1233 ASSERT_EQ(EBADF, errno);
1234}
Elliott Hughes2704bd12016-01-20 17:14:53 -08001235
1236TEST(STDIO_TEST, fseek_ftell_unseekable) {
1237#if defined(__BIONIC__) // glibc has fopencookie instead.
1238 auto read_fn = [](void*, char*, int) { return -1; };
1239 FILE* fp = funopen(nullptr, read_fn, nullptr, nullptr, nullptr);
1240 ASSERT_TRUE(fp != nullptr);
1241
1242 // Check that ftell balks on an unseekable FILE*.
1243 errno = 0;
1244 ASSERT_EQ(-1, ftell(fp));
1245 ASSERT_EQ(ESPIPE, errno);
1246
1247 // SEEK_CUR is rewritten as SEEK_SET internally...
1248 errno = 0;
1249 ASSERT_EQ(-1, fseek(fp, 0, SEEK_CUR));
1250 ASSERT_EQ(ESPIPE, errno);
1251
1252 // ...so it's worth testing the direct seek path too.
1253 errno = 0;
1254 ASSERT_EQ(-1, fseek(fp, 0, SEEK_SET));
1255 ASSERT_EQ(ESPIPE, errno);
1256
1257 fclose(fp);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08001258#else
1259 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
1260#endif
1261}
1262
1263TEST(STDIO_TEST, funopen_EINVAL) {
1264#if defined(__BIONIC__)
1265 errno = 0;
1266 ASSERT_EQ(nullptr, funopen(nullptr, nullptr, nullptr, nullptr, nullptr));
1267 ASSERT_EQ(EINVAL, errno);
1268#else
1269 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
1270#endif
1271}
1272
1273TEST(STDIO_TEST, funopen_seek) {
1274#if defined(__BIONIC__)
1275 auto read_fn = [](void*, char*, int) { return -1; };
1276
1277 auto seek_fn = [](void*, fpos_t, int) -> fpos_t { return 0xfedcba12; };
1278 auto seek64_fn = [](void*, fpos64_t, int) -> fpos64_t { return 0xfedcba12345678; };
1279
1280 FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr);
1281 ASSERT_TRUE(fp != nullptr);
1282 fpos_t pos;
Elliott Hughes955426e2016-01-26 18:25:52 -08001283#if defined(__LP64__)
1284 EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno);
1285 EXPECT_EQ(0xfedcba12LL, pos);
1286#else
1287 EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno);
1288 EXPECT_EQ(EOVERFLOW, errno);
1289#endif
Elliott Hughes03e65eb2016-01-26 14:13:04 -08001290
1291 FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr);
1292 ASSERT_TRUE(fp64 != nullptr);
1293 fpos64_t pos64;
Elliott Hughes955426e2016-01-26 18:25:52 -08001294 EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno);
1295 EXPECT_EQ(0xfedcba12345678, pos64);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08001296#else
1297 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
Elliott Hughes2704bd12016-01-20 17:14:53 -08001298#endif
1299}
Elliott Hughes71288cb2016-01-22 19:22:44 -08001300
1301TEST(STDIO_TEST, lots_of_concurrent_files) {
1302 std::vector<TemporaryFile*> tfs;
1303 std::vector<FILE*> fps;
1304
1305 for (size_t i = 0; i < 256; ++i) {
1306 TemporaryFile* tf = new TemporaryFile;
1307 tfs.push_back(tf);
1308 FILE* fp = fopen(tf->filename, "w+");
1309 fps.push_back(fp);
1310 fprintf(fp, "hello %zu!\n", i);
1311 fflush(fp);
1312 }
1313
1314 for (size_t i = 0; i < 256; ++i) {
Elliott Hughes71288cb2016-01-22 19:22:44 -08001315 char expected[BUFSIZ];
1316 snprintf(expected, sizeof(expected), "hello %zu!\n", i);
Elliott Hughes71288cb2016-01-22 19:22:44 -08001317
Elliott Hughes70715da2016-08-01 16:35:17 -07001318 AssertFileIs(fps[i], expected);
Elliott Hughes71288cb2016-01-22 19:22:44 -08001319 fclose(fps[i]);
1320 delete tfs[i];
1321 }
1322}
Elliott Hughes9677fab2016-01-25 15:50:59 -08001323
1324static void AssertFileOffsetAt(FILE* fp, off64_t offset) {
1325 EXPECT_EQ(offset, ftell(fp));
1326 EXPECT_EQ(offset, ftello(fp));
Elliott Hughese4fa6e92016-02-02 22:39:15 -08001327 EXPECT_EQ(offset, ftello64(fp));
Elliott Hughes9677fab2016-01-25 15:50:59 -08001328 fpos_t pos;
1329 fpos64_t pos64;
1330 EXPECT_EQ(0, fgetpos(fp, &pos));
1331 EXPECT_EQ(0, fgetpos64(fp, &pos64));
1332#if defined(__BIONIC__)
1333 EXPECT_EQ(offset, static_cast<off64_t>(pos));
1334 EXPECT_EQ(offset, static_cast<off64_t>(pos64));
1335#else
1336 GTEST_LOG_(INFO) << "glibc's fpos_t is opaque.\n";
1337#endif
1338}
1339
1340TEST(STDIO_TEST, seek_tell_family_smoke) {
1341 TemporaryFile tf;
1342 FILE* fp = fdopen(tf.fd, "w+");
1343
1344 // Initially we should be at 0.
1345 AssertFileOffsetAt(fp, 0);
1346
1347 // Seek to offset 8192.
1348 ASSERT_EQ(0, fseek(fp, 8192, SEEK_SET));
1349 AssertFileOffsetAt(fp, 8192);
1350 fpos_t eight_k_pos;
1351 ASSERT_EQ(0, fgetpos(fp, &eight_k_pos));
1352
1353 // Seek forward another 8192...
1354 ASSERT_EQ(0, fseek(fp, 8192, SEEK_CUR));
1355 AssertFileOffsetAt(fp, 8192 + 8192);
1356 fpos64_t sixteen_k_pos64;
1357 ASSERT_EQ(0, fgetpos64(fp, &sixteen_k_pos64));
1358
1359 // Seek back 8192...
1360 ASSERT_EQ(0, fseek(fp, -8192, SEEK_CUR));
1361 AssertFileOffsetAt(fp, 8192);
1362
1363 // Since we haven't written anything, the end is also at 0.
1364 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1365 AssertFileOffsetAt(fp, 0);
1366
1367 // Check that our fpos64_t from 16KiB works...
1368 ASSERT_EQ(0, fsetpos64(fp, &sixteen_k_pos64));
1369 AssertFileOffsetAt(fp, 8192 + 8192);
1370 // ...as does our fpos_t from 8192.
1371 ASSERT_EQ(0, fsetpos(fp, &eight_k_pos));
1372 AssertFileOffsetAt(fp, 8192);
1373
1374 // Do fseeko and fseeko64 work too?
1375 ASSERT_EQ(0, fseeko(fp, 1234, SEEK_SET));
1376 AssertFileOffsetAt(fp, 1234);
1377 ASSERT_EQ(0, fseeko64(fp, 5678, SEEK_SET));
1378 AssertFileOffsetAt(fp, 5678);
1379
1380 fclose(fp);
1381}
1382
1383TEST(STDIO_TEST, fseek_fseeko_EINVAL) {
1384 TemporaryFile tf;
1385 FILE* fp = fdopen(tf.fd, "w+");
1386
1387 // Bad whence.
1388 errno = 0;
1389 ASSERT_EQ(-1, fseek(fp, 0, 123));
1390 ASSERT_EQ(EINVAL, errno);
1391 errno = 0;
1392 ASSERT_EQ(-1, fseeko(fp, 0, 123));
1393 ASSERT_EQ(EINVAL, errno);
1394 errno = 0;
1395 ASSERT_EQ(-1, fseeko64(fp, 0, 123));
1396 ASSERT_EQ(EINVAL, errno);
1397
1398 // Bad offset.
1399 errno = 0;
1400 ASSERT_EQ(-1, fseek(fp, -1, SEEK_SET));
1401 ASSERT_EQ(EINVAL, errno);
1402 errno = 0;
1403 ASSERT_EQ(-1, fseeko(fp, -1, SEEK_SET));
1404 ASSERT_EQ(EINVAL, errno);
1405 errno = 0;
1406 ASSERT_EQ(-1, fseeko64(fp, -1, SEEK_SET));
1407 ASSERT_EQ(EINVAL, errno);
1408
1409 fclose(fp);
1410}
Elliott Hughes20788ae2016-06-09 15:16:32 -07001411
1412TEST(STDIO_TEST, ctermid) {
1413 ASSERT_STREQ("/dev/tty", ctermid(nullptr));
1414
1415 char buf[L_ctermid] = {};
1416 ASSERT_EQ(buf, ctermid(buf));
1417 ASSERT_STREQ("/dev/tty", buf);
1418}
Elliott Hughesd1f25a72016-08-05 15:53:03 -07001419
1420TEST(STDIO_TEST, remove) {
1421 struct stat sb;
1422
1423 TemporaryFile tf;
1424 ASSERT_EQ(0, remove(tf.filename));
1425 ASSERT_EQ(-1, lstat(tf.filename, &sb));
1426 ASSERT_EQ(ENOENT, errno);
1427
1428 TemporaryDir td;
1429 ASSERT_EQ(0, remove(td.dirname));
1430 ASSERT_EQ(-1, lstat(td.dirname, &sb));
1431 ASSERT_EQ(ENOENT, errno);
1432
1433 errno = 0;
1434 ASSERT_EQ(-1, remove(tf.filename));
1435 ASSERT_EQ(ENOENT, errno);
1436
1437 errno = 0;
1438 ASSERT_EQ(-1, remove(td.dirname));
1439 ASSERT_EQ(ENOENT, errno);
1440}
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001441
1442TEST(STDIO_DEATHTEST, snprintf_30445072_known_buffer_size) {
1443 char buf[16];
1444 ASSERT_EXIT(snprintf(buf, atol("-1"), "hello"),
1445 testing::KilledBySignal(SIGABRT),
1446#if defined(NOFORTIFY)
1447 "FORTIFY: vsnprintf: size .* > SSIZE_MAX"
1448#else
1449 "FORTIFY: vsnprintf: prevented .*-byte write into 16-byte buffer"
1450#endif
1451 );
1452}
1453
1454TEST(STDIO_DEATHTEST, snprintf_30445072_unknown_buffer_size) {
1455 std::string buf = "world";
1456 ASSERT_EXIT(snprintf(&buf[0], atol("-1"), "hello"),
1457 testing::KilledBySignal(SIGABRT),
1458 "FORTIFY: vsnprintf: size .* > SSIZE_MAX");
1459}
1460
1461TEST(STDIO_TEST, sprintf_30445072) {
1462 std::string buf = "world";
1463 sprintf(&buf[0], "hello");
1464 ASSERT_EQ(buf, "hello");
1465}