blob: 1f27c832a2966f81af60632e392a52bcb45d04ef [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 Hughes3a4c4542017-07-19 17:20:24 -070030#include <string>
Elliott Hughese6bb5a22015-01-23 17:48:15 -080031#include <vector>
32
Elliott Hughesfb3873d2016-08-10 11:07:54 -070033#include "BionicDeathTest.h"
Calin Juravle03e4ebe2014-05-08 14:42:06 +010034#include "TemporaryFile.h"
Josh Gao2f06e102017-01-10 13:00:37 -080035#include "utils.h"
Elliott Hughes91875dc2012-09-24 17:55:15 -070036
Christopher Ferris13f26a72016-01-13 13:47:58 -080037#if defined(NOFORTIFY)
38#define STDIO_TEST stdio_nofortify
Elliott Hughesfb3873d2016-08-10 11:07:54 -070039#define STDIO_DEATHTEST stdio_nofortify_DeathTest
Christopher Ferris13f26a72016-01-13 13:47:58 -080040#else
41#define STDIO_TEST stdio
Elliott Hughesfb3873d2016-08-10 11:07:54 -070042#define STDIO_DEATHTEST stdio_DeathTest
Christopher Ferris13f26a72016-01-13 13:47:58 -080043#endif
44
Elliott Hughes3a4c4542017-07-19 17:20:24 -070045using namespace std::string_literals;
46
Elliott Hughesfb3873d2016-08-10 11:07:54 -070047class stdio_DeathTest : public BionicDeathTest {};
48class stdio_nofortify_DeathTest : public BionicDeathTest {};
49
Elliott Hughes70715da2016-08-01 16:35:17 -070050static void AssertFileIs(FILE* fp, const char* expected, bool is_fmemopen = false) {
51 rewind(fp);
52
53 char line[1024];
Josh Gao2f06e102017-01-10 13:00:37 -080054 memset(line, 0xff, sizeof(line));
Elliott Hughes70715da2016-08-01 16:35:17 -070055 ASSERT_EQ(line, fgets(line, sizeof(line), fp));
56 ASSERT_STREQ(expected, line);
57
58 if (is_fmemopen) {
59 // fmemopen appends a trailing NUL byte, which probably shouldn't show up as an
60 // extra empty line, but does on every C library I tested...
61 ASSERT_EQ(line, fgets(line, sizeof(line), fp));
62 ASSERT_STREQ("", line);
63 }
64
65 // Make sure there isn't anything else in the file.
66 ASSERT_EQ(nullptr, fgets(line, sizeof(line), fp)) << "junk at end of file: " << line;
67}
68
Christopher Ferris13f26a72016-01-13 13:47:58 -080069TEST(STDIO_TEST, flockfile_18208568_stderr) {
Elliott Hughes6a03abc2014-11-03 12:32:17 -080070 // Check that we have a _recursive_ mutex for flockfile.
71 flockfile(stderr);
72 feof(stderr); // We don't care about the result, but this needs to take the lock.
73 funlockfile(stderr);
74}
75
Christopher Ferris13f26a72016-01-13 13:47:58 -080076TEST(STDIO_TEST, flockfile_18208568_regular) {
Elliott Hughes6a03abc2014-11-03 12:32:17 -080077 // We never had a bug for streams other than stdin/stdout/stderr, but test anyway.
78 FILE* fp = fopen("/dev/null", "w");
79 ASSERT_TRUE(fp != NULL);
80 flockfile(fp);
81 feof(fp);
82 funlockfile(fp);
83 fclose(fp);
84}
85
Christopher Ferris13f26a72016-01-13 13:47:58 -080086TEST(STDIO_TEST, tmpfile_fileno_fprintf_rewind_fgets) {
Elliott Hughes91875dc2012-09-24 17:55:15 -070087 FILE* fp = tmpfile();
88 ASSERT_TRUE(fp != NULL);
89
90 int fd = fileno(fp);
91 ASSERT_NE(fd, -1);
92
93 struct stat sb;
94 int rc = fstat(fd, &sb);
95 ASSERT_NE(rc, -1);
96 ASSERT_EQ(sb.st_mode & 0777, 0600U);
97
98 rc = fprintf(fp, "hello\n");
99 ASSERT_EQ(rc, 6);
100
Elliott Hughes70715da2016-08-01 16:35:17 -0700101 AssertFileIs(fp, "hello\n");
Elliott Hughes91875dc2012-09-24 17:55:15 -0700102 fclose(fp);
103}
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300104
Elliott Hughesf226ee52016-02-03 11:24:28 -0800105TEST(STDIO_TEST, tmpfile64) {
106 FILE* fp = tmpfile64();
107 ASSERT_TRUE(fp != nullptr);
108 fclose(fp);
109}
110
Christopher Ferris13f26a72016-01-13 13:47:58 -0800111TEST(STDIO_TEST, dprintf) {
Calin Juravle6afb2a92014-05-22 11:47:47 +0100112 TemporaryFile tf;
113
114 int rc = dprintf(tf.fd, "hello\n");
115 ASSERT_EQ(rc, 6);
116
Yabin Cui5ca4a9e2014-11-06 19:55:09 -0800117 lseek(tf.fd, 0, SEEK_SET);
Christopher Ferris9e01ea62014-05-29 12:49:35 -0700118 FILE* tfile = fdopen(tf.fd, "r");
119 ASSERT_TRUE(tfile != NULL);
Calin Juravle6afb2a92014-05-22 11:47:47 +0100120
Elliott Hughes70715da2016-08-01 16:35:17 -0700121 AssertFileIs(tfile, "hello\n");
Christopher Ferris9e01ea62014-05-29 12:49:35 -0700122 fclose(tfile);
Calin Juravle6afb2a92014-05-22 11:47:47 +0100123}
124
Christopher Ferris13f26a72016-01-13 13:47:58 -0800125TEST(STDIO_TEST, getdelim) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300126 FILE* fp = tmpfile();
127 ASSERT_TRUE(fp != NULL);
128
129 const char* line_written = "This is a test";
130 int rc = fprintf(fp, "%s", line_written);
131 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
132
133 rewind(fp);
134
135 char* word_read = NULL;
136 size_t allocated_length = 0;
137
138 const char* expected[] = { "This ", " ", "is ", "a ", "test" };
139 for (size_t i = 0; i < 5; ++i) {
140 ASSERT_FALSE(feof(fp));
141 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i])));
142 ASSERT_GE(allocated_length, strlen(expected[i]));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800143 ASSERT_STREQ(expected[i], word_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300144 }
145 // The last read should have set the end-of-file indicator for the stream.
146 ASSERT_TRUE(feof(fp));
147 clearerr(fp);
148
149 // getdelim returns -1 but doesn't set errno if we're already at EOF.
150 // It should set the end-of-file indicator for the stream, though.
151 errno = 0;
152 ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800153 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300154 ASSERT_TRUE(feof(fp));
155
156 free(word_read);
157 fclose(fp);
158}
159
Christopher Ferris13f26a72016-01-13 13:47:58 -0800160TEST(STDIO_TEST, getdelim_invalid) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300161 FILE* fp = tmpfile();
Elliott Hughes6ad8f762013-12-19 14:56:17 -0800162 ASSERT_TRUE(fp != NULL);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300163
164 char* buffer = NULL;
165 size_t buffer_length = 0;
166
167 // The first argument can't be NULL.
168 errno = 0;
169 ASSERT_EQ(getdelim(NULL, &buffer_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800170 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300171
172 // The second argument can't be NULL.
173 errno = 0;
174 ASSERT_EQ(getdelim(&buffer, NULL, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800175 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300176
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700177 // The underlying fd can't be closed.
178 ASSERT_EQ(0, close(fileno(fp)));
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300179 errno = 0;
180 ASSERT_EQ(getdelim(&buffer, &buffer_length, ' ', fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800181 ASSERT_EQ(EBADF, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700182 fclose(fp);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300183}
184
Christopher Ferris13f26a72016-01-13 13:47:58 -0800185TEST(STDIO_TEST, getdelim_directory) {
Elliott Hughes694fd2d2015-04-05 10:51:56 -0700186 FILE* fp = fopen("/proc", "r");
187 ASSERT_TRUE(fp != NULL);
188 char* word_read;
189 size_t allocated_length;
190 ASSERT_EQ(-1, getdelim(&word_read, &allocated_length, ' ', fp));
191 fclose(fp);
192}
193
Christopher Ferris13f26a72016-01-13 13:47:58 -0800194TEST(STDIO_TEST, getline) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300195 FILE* fp = tmpfile();
196 ASSERT_TRUE(fp != NULL);
197
198 const char* line_written = "This is a test for getline\n";
199 const size_t line_count = 5;
200
201 for (size_t i = 0; i < line_count; ++i) {
202 int rc = fprintf(fp, "%s", line_written);
203 ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
204 }
205
206 rewind(fp);
207
208 char* line_read = NULL;
209 size_t allocated_length = 0;
210
211 size_t read_line_count = 0;
212 ssize_t read_char_count;
213 while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) {
214 ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written)));
215 ASSERT_GE(allocated_length, strlen(line_written));
Elliott Hughes0ed7e082015-01-22 15:13:38 -0800216 ASSERT_STREQ(line_written, line_read);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300217 ++read_line_count;
218 }
219 ASSERT_EQ(read_line_count, line_count);
220
221 // The last read should have set the end-of-file indicator for the stream.
222 ASSERT_TRUE(feof(fp));
223 clearerr(fp);
224
225 // getline returns -1 but doesn't set errno if we're already at EOF.
226 // It should set the end-of-file indicator for the stream, though.
227 errno = 0;
228 ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800229 ASSERT_EQ(0, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300230 ASSERT_TRUE(feof(fp));
231
232 free(line_read);
233 fclose(fp);
234}
235
Christopher Ferris13f26a72016-01-13 13:47:58 -0800236TEST(STDIO_TEST, getline_invalid) {
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300237 FILE* fp = tmpfile();
Elliott Hughes6ad8f762013-12-19 14:56:17 -0800238 ASSERT_TRUE(fp != NULL);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300239
240 char* buffer = NULL;
241 size_t buffer_length = 0;
242
243 // The first argument can't be NULL.
244 errno = 0;
245 ASSERT_EQ(getline(NULL, &buffer_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800246 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300247
248 // The second argument can't be NULL.
249 errno = 0;
250 ASSERT_EQ(getline(&buffer, NULL, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800251 ASSERT_EQ(EINVAL, errno);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300252
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700253 // The underlying fd can't be closed.
254 ASSERT_EQ(0, close(fileno(fp)));
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300255 errno = 0;
256 ASSERT_EQ(getline(&buffer, &buffer_length, fp), -1);
Elliott Hughes5e3fc432013-02-11 16:36:48 -0800257 ASSERT_EQ(EBADF, errno);
Elliott Hughes20f8aec2014-05-12 15:15:37 -0700258 fclose(fp);
Irina Tirdeaeac9eb42012-09-08 09:28:30 +0300259}
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000260
Christopher Ferris13f26a72016-01-13 13:47:58 -0800261TEST(STDIO_TEST, printf_ssize_t) {
Elliott Hughese2556422013-02-28 10:51:14 -0800262 // http://b/8253769
Elliott Hughese2556422013-02-28 10:51:14 -0800263 ASSERT_EQ(sizeof(ssize_t), sizeof(long int));
Elliott Hughesb6e22482013-03-08 15:28:52 -0800264 ASSERT_EQ(sizeof(ssize_t), sizeof(size_t));
265 // For our 32-bit ABI, we had a ssize_t definition that confuses GCC into saying:
Thorsten Glaserc641caf2013-02-17 16:50:58 +0000266 // error: format '%zd' expects argument of type 'signed size_t',
267 // but argument 4 has type 'ssize_t {aka long int}' [-Werror=format]
268 ssize_t v = 1;
269 char buf[32];
270 snprintf(buf, sizeof(buf), "%zd", v);
271}
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800272
Elliott Hughes05493712014-04-17 17:30:03 -0700273// https://code.google.com/p/android/issues/detail?id=64886
Christopher Ferris13f26a72016-01-13 13:47:58 -0800274TEST(STDIO_TEST, snprintf_a) {
Elliott Hughes05493712014-04-17 17:30:03 -0700275 char buf[BUFSIZ];
276 EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235));
277 EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf);
278}
279
Christopher Ferris13f26a72016-01-13 13:47:58 -0800280TEST(STDIO_TEST, snprintf_lc) {
Elliott Hughes05493712014-04-17 17:30:03 -0700281 char buf[BUFSIZ];
282 wint_t wc = L'a';
283 EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc));
284 EXPECT_STREQ("<a>", buf);
285}
286
Christopher Ferris13f26a72016-01-13 13:47:58 -0800287TEST(STDIO_TEST, snprintf_ls) {
Elliott Hughes05493712014-04-17 17:30:03 -0700288 char buf[BUFSIZ];
289 wchar_t* ws = NULL;
290 EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws));
291 EXPECT_STREQ("<(null)>", buf);
292
293 wchar_t chars[] = { L'h', L'i', 0 };
294 ws = chars;
295 EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws));
296 EXPECT_STREQ("<hi>", buf);
297}
298
Christopher Ferris13f26a72016-01-13 13:47:58 -0800299TEST(STDIO_TEST, snprintf_n) {
Elliott Hughes063525c2014-05-13 11:19:57 -0700300#if defined(__BIONIC__)
Elliott Hughese2341d02014-05-02 18:16:32 -0700301 // http://b/14492135
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700302 char buf[32];
Elliott Hughese2341d02014-05-02 18:16:32 -0700303 int i = 1234;
304 EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
305 EXPECT_EQ(1234, i);
306 EXPECT_STREQ("a n b", buf);
307#else
Elliott Hughes9677fab2016-01-25 15:50:59 -0800308 GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
Elliott Hughese2341d02014-05-02 18:16:32 -0700309#endif
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700310}
Elliott Hughes7248a2d2013-09-24 18:01:33 -0700311
Christopher Ferris13f26a72016-01-13 13:47:58 -0800312TEST(STDIO_TEST, snprintf_smoke) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700313 char buf[BUFSIZ];
314
315 snprintf(buf, sizeof(buf), "a");
316 EXPECT_STREQ("a", buf);
317
318 snprintf(buf, sizeof(buf), "%%");
319 EXPECT_STREQ("%", buf);
320
321 snprintf(buf, sizeof(buf), "01234");
322 EXPECT_STREQ("01234", buf);
323
324 snprintf(buf, sizeof(buf), "a%sb", "01234");
325 EXPECT_STREQ("a01234b", buf);
326
327 char* s = NULL;
328 snprintf(buf, sizeof(buf), "a%sb", s);
329 EXPECT_STREQ("a(null)b", buf);
330
331 snprintf(buf, sizeof(buf), "aa%scc", "bb");
332 EXPECT_STREQ("aabbcc", buf);
333
334 snprintf(buf, sizeof(buf), "a%cc", 'b');
335 EXPECT_STREQ("abc", buf);
336
337 snprintf(buf, sizeof(buf), "a%db", 1234);
338 EXPECT_STREQ("a1234b", buf);
339
340 snprintf(buf, sizeof(buf), "a%db", -8123);
341 EXPECT_STREQ("a-8123b", buf);
342
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700343 snprintf(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010));
Elliott Hughes1d13c642013-09-23 16:02:39 -0700344 EXPECT_STREQ("a16b", buf);
345
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700346 snprintf(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
Elliott Hughes1d13c642013-09-23 16:02:39 -0700347 EXPECT_STREQ("a16b", buf);
348
349 snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
350 EXPECT_STREQ("a68719476736b", buf);
351
352 snprintf(buf, sizeof(buf), "a%ldb", 70000L);
353 EXPECT_STREQ("a70000b", buf);
354
355 snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
356 EXPECT_STREQ("a0xb0001234b", buf);
357
358 snprintf(buf, sizeof(buf), "a%xz", 0x12ab);
359 EXPECT_STREQ("a12abz", buf);
360
361 snprintf(buf, sizeof(buf), "a%Xz", 0x12ab);
362 EXPECT_STREQ("a12ABz", buf);
363
364 snprintf(buf, sizeof(buf), "a%08xz", 0x123456);
365 EXPECT_STREQ("a00123456z", buf);
366
367 snprintf(buf, sizeof(buf), "a%5dz", 1234);
368 EXPECT_STREQ("a 1234z", buf);
369
370 snprintf(buf, sizeof(buf), "a%05dz", 1234);
371 EXPECT_STREQ("a01234z", buf);
372
373 snprintf(buf, sizeof(buf), "a%8dz", 1234);
374 EXPECT_STREQ("a 1234z", buf);
375
376 snprintf(buf, sizeof(buf), "a%-8dz", 1234);
377 EXPECT_STREQ("a1234 z", buf);
378
379 snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef");
380 EXPECT_STREQ("Aabcdef Z", buf);
381
382 snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
383 EXPECT_STREQ("Ahello:1234Z", buf);
384
385 snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
386 EXPECT_STREQ("a005:5:05z", buf);
387
388 void* p = NULL;
389 snprintf(buf, sizeof(buf), "a%d,%pz", 5, p);
Christopher Ferris13613132013-10-28 15:24:04 -0700390#if defined(__BIONIC__)
Elliott Hughes1d13c642013-09-23 16:02:39 -0700391 EXPECT_STREQ("a5,0x0z", buf);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800392#else // __BIONIC__
Christopher Ferris13613132013-10-28 15:24:04 -0700393 EXPECT_STREQ("a5,(nil)z", buf);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800394#endif // __BIONIC__
Elliott Hughes1d13c642013-09-23 16:02:39 -0700395
396 snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
397 EXPECT_STREQ("a68719476736,6,7,8z", buf);
398
399 snprintf(buf, sizeof(buf), "a_%f_b", 1.23f);
400 EXPECT_STREQ("a_1.230000_b", buf);
401
Stephen Hines6c7b3cb2013-10-11 16:03:21 -0700402 snprintf(buf, sizeof(buf), "a_%g_b", 3.14);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700403 EXPECT_STREQ("a_3.14_b", buf);
Alexander Ivchenkoedd7c2e2014-04-01 17:01:39 +0400404
405 snprintf(buf, sizeof(buf), "%1$s %1$s", "print_me_twice");
406 EXPECT_STREQ("print_me_twice print_me_twice", buf);
Elliott Hughes1d13c642013-09-23 16:02:39 -0700407}
408
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800409template <typename T>
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700410static void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...),
411 int sscanf_fn(const T*, const T*, ...),
412 const T* fmt_string, const T* fmt, const T* fmt_plus,
413 const T* minus_inf, const T* inf_, const T* plus_inf,
414 const T* minus_nan, const T* nan_, const T* plus_nan) {
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800415 T buf[BUFSIZ];
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700416 float f;
Elliott Hughes7823f322014-04-14 12:11:28 -0700417
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700418 // NaN.
419
420 snprintf_fn(buf, sizeof(buf), fmt, nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800421 EXPECT_STREQ(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, -nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800426 EXPECT_STREQ(minus_nan, buf) << fmt;
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(plus_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));
434
435 snprintf_fn(buf, sizeof(buf), fmt_plus, -nanf(""));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800436 EXPECT_STREQ(minus_nan, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700437 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
438 EXPECT_TRUE(isnan(f));
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800439
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700440 // Inf.
441
442 snprintf_fn(buf, sizeof(buf), fmt, HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800443 EXPECT_STREQ(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, -HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800448 EXPECT_STREQ(minus_inf, buf) << fmt;
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(plus_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 snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VALF);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800458 EXPECT_STREQ(minus_inf, buf) << fmt_plus;
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700459 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f));
460 EXPECT_EQ(-HUGE_VALF, f);
461
462 // Check case-insensitivity.
463 snprintf_fn(buf, sizeof(buf), fmt_string, "[InFiNiTy]");
464 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f)) << buf;
465 EXPECT_EQ(HUGE_VALF, f);
466 snprintf_fn(buf, sizeof(buf), fmt_string, "[NaN]");
467 EXPECT_EQ(1, sscanf_fn(buf, fmt, &f)) << buf;
468 EXPECT_TRUE(isnan(f));
Elliott Hughes7823f322014-04-14 12:11:28 -0700469}
470
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700471TEST(STDIO_TEST, snprintf_sscanf_inf_nan) {
472 CheckInfNan(snprintf, sscanf, "%s",
473 "[%a]", "[%+a]",
474 "[-inf]", "[inf]", "[+inf]",
475 "[-nan]", "[nan]", "[+nan]");
476 CheckInfNan(snprintf, sscanf, "%s",
477 "[%A]", "[%+A]",
478 "[-INF]", "[INF]", "[+INF]",
479 "[-NAN]", "[NAN]", "[+NAN]");
480 CheckInfNan(snprintf, sscanf, "%s",
481 "[%e]", "[%+e]",
482 "[-inf]", "[inf]", "[+inf]",
483 "[-nan]", "[nan]", "[+nan]");
484 CheckInfNan(snprintf, sscanf, "%s",
485 "[%E]", "[%+E]",
486 "[-INF]", "[INF]", "[+INF]",
487 "[-NAN]", "[NAN]", "[+NAN]");
488 CheckInfNan(snprintf, sscanf, "%s",
489 "[%f]", "[%+f]",
490 "[-inf]", "[inf]", "[+inf]",
491 "[-nan]", "[nan]", "[+nan]");
492 CheckInfNan(snprintf, sscanf, "%s",
493 "[%F]", "[%+F]",
494 "[-INF]", "[INF]", "[+INF]",
495 "[-NAN]", "[NAN]", "[+NAN]");
496 CheckInfNan(snprintf, sscanf, "%s",
497 "[%g]", "[%+g]",
498 "[-inf]", "[inf]", "[+inf]",
499 "[-nan]", "[nan]", "[+nan]");
500 CheckInfNan(snprintf, sscanf, "%s",
501 "[%G]", "[%+G]",
502 "[-INF]", "[INF]", "[+INF]",
503 "[-NAN]", "[NAN]", "[+NAN]");
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800504}
Elliott Hughes7823f322014-04-14 12:11:28 -0700505
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700506TEST(STDIO_TEST, swprintf_swscanf_inf_nan) {
507 CheckInfNan(swprintf, swscanf, L"%s",
508 L"[%a]", L"[%+a]",
509 L"[-inf]", L"[inf]", L"[+inf]",
510 L"[-nan]", L"[nan]", L"[+nan]");
511 CheckInfNan(swprintf, swscanf, L"%s",
512 L"[%A]", L"[%+A]",
513 L"[-INF]", L"[INF]", L"[+INF]",
514 L"[-NAN]", L"[NAN]", L"[+NAN]");
515 CheckInfNan(swprintf, swscanf, L"%s",
516 L"[%e]", L"[%+e]",
517 L"[-inf]", L"[inf]", L"[+inf]",
518 L"[-nan]", L"[nan]", L"[+nan]");
519 CheckInfNan(swprintf, swscanf, L"%s",
520 L"[%E]", L"[%+E]",
521 L"[-INF]", L"[INF]", L"[+INF]",
522 L"[-NAN]", L"[NAN]", L"[+NAN]");
523 CheckInfNan(swprintf, swscanf, L"%s",
524 L"[%f]", L"[%+f]",
525 L"[-inf]", L"[inf]", L"[+inf]",
526 L"[-nan]", L"[nan]", L"[+nan]");
527 CheckInfNan(swprintf, swscanf, L"%s",
528 L"[%F]", L"[%+F]",
529 L"[-INF]", L"[INF]", L"[+INF]",
530 L"[-NAN]", L"[NAN]", L"[+NAN]");
531 CheckInfNan(swprintf, swscanf, L"%s",
532 L"[%g]", L"[%+g]",
533 L"[-inf]", L"[inf]", L"[+inf]",
534 L"[-nan]", L"[nan]", L"[+nan]");
535 CheckInfNan(swprintf, swscanf, L"%s",
536 L"[%G]", L"[%+G]",
537 L"[-INF]", L"[INF]", L"[+INF]",
538 L"[-NAN]", L"[NAN]", L"[+NAN]");
Elliott Hughes7823f322014-04-14 12:11:28 -0700539}
540
Christopher Ferris13f26a72016-01-13 13:47:58 -0800541TEST(STDIO_TEST, snprintf_d_INT_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700542 char buf[BUFSIZ];
543 snprintf(buf, sizeof(buf), "%d", INT_MAX);
544 EXPECT_STREQ("2147483647", buf);
545}
546
Christopher Ferris13f26a72016-01-13 13:47:58 -0800547TEST(STDIO_TEST, snprintf_d_INT_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700548 char buf[BUFSIZ];
549 snprintf(buf, sizeof(buf), "%d", INT_MIN);
550 EXPECT_STREQ("-2147483648", buf);
551}
552
Christopher Ferris13f26a72016-01-13 13:47:58 -0800553TEST(STDIO_TEST, snprintf_ld_LONG_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700554 char buf[BUFSIZ];
555 snprintf(buf, sizeof(buf), "%ld", LONG_MAX);
Josh Gaob36efa42016-09-15 13:55:41 -0700556#if defined(__LP64__)
Elliott Hughes925753a2013-10-18 13:17:18 -0700557 EXPECT_STREQ("9223372036854775807", buf);
558#else
Elliott Hughes1d13c642013-09-23 16:02:39 -0700559 EXPECT_STREQ("2147483647", buf);
Elliott Hughes925753a2013-10-18 13:17:18 -0700560#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700561}
562
Christopher Ferris13f26a72016-01-13 13:47:58 -0800563TEST(STDIO_TEST, snprintf_ld_LONG_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700564 char buf[BUFSIZ];
565 snprintf(buf, sizeof(buf), "%ld", LONG_MIN);
Josh Gaob36efa42016-09-15 13:55:41 -0700566#if defined(__LP64__)
Elliott Hughes925753a2013-10-18 13:17:18 -0700567 EXPECT_STREQ("-9223372036854775808", buf);
568#else
Elliott Hughes1d13c642013-09-23 16:02:39 -0700569 EXPECT_STREQ("-2147483648", buf);
Elliott Hughes925753a2013-10-18 13:17:18 -0700570#endif
Elliott Hughes1d13c642013-09-23 16:02:39 -0700571}
572
Christopher Ferris13f26a72016-01-13 13:47:58 -0800573TEST(STDIO_TEST, snprintf_lld_LLONG_MAX) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700574 char buf[BUFSIZ];
575 snprintf(buf, sizeof(buf), "%lld", LLONG_MAX);
576 EXPECT_STREQ("9223372036854775807", buf);
577}
578
Christopher Ferris13f26a72016-01-13 13:47:58 -0800579TEST(STDIO_TEST, snprintf_lld_LLONG_MIN) {
Elliott Hughes1d13c642013-09-23 16:02:39 -0700580 char buf[BUFSIZ];
581 snprintf(buf, sizeof(buf), "%lld", LLONG_MIN);
582 EXPECT_STREQ("-9223372036854775808", buf);
583}
584
Christopher Ferris13f26a72016-01-13 13:47:58 -0800585TEST(STDIO_TEST, snprintf_e) {
Elliott Hughes4bd97ce2014-04-10 17:48:14 -0700586 char buf[BUFSIZ];
587
588 snprintf(buf, sizeof(buf), "%e", 1.5);
589 EXPECT_STREQ("1.500000e+00", buf);
590
591 snprintf(buf, sizeof(buf), "%Le", 1.5l);
592 EXPECT_STREQ("1.500000e+00", buf);
593}
594
Christopher Ferris13f26a72016-01-13 13:47:58 -0800595TEST(STDIO_TEST, snprintf_negative_zero_5084292) {
Elliott Hughese77f38f2014-05-14 12:39:12 -0700596 char buf[BUFSIZ];
597
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800598 snprintf(buf, sizeof(buf), "%e", -0.0);
599 EXPECT_STREQ("-0.000000e+00", buf);
600 snprintf(buf, sizeof(buf), "%E", -0.0);
601 EXPECT_STREQ("-0.000000E+00", buf);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700602 snprintf(buf, sizeof(buf), "%f", -0.0);
603 EXPECT_STREQ("-0.000000", buf);
Elliott Hughes1b18aff2014-12-16 14:45:32 -0800604 snprintf(buf, sizeof(buf), "%F", -0.0);
605 EXPECT_STREQ("-0.000000", buf);
606 snprintf(buf, sizeof(buf), "%g", -0.0);
607 EXPECT_STREQ("-0", buf);
608 snprintf(buf, sizeof(buf), "%G", -0.0);
609 EXPECT_STREQ("-0", buf);
610 snprintf(buf, sizeof(buf), "%a", -0.0);
611 EXPECT_STREQ("-0x0p+0", buf);
612 snprintf(buf, sizeof(buf), "%A", -0.0);
613 EXPECT_STREQ("-0X0P+0", buf);
Elliott Hughese77f38f2014-05-14 12:39:12 -0700614}
615
Christopher Ferris13f26a72016-01-13 13:47:58 -0800616TEST(STDIO_TEST, snprintf_utf8_15439554) {
Dan Albert1aec7c12014-07-30 10:53:48 -0700617 locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0);
Wally Yaua40fdbd2014-08-26 09:47:23 -0700618 locale_t old_locale = uselocale(cloc);
Dan Albert1aec7c12014-07-30 10:53:48 -0700619
Elliott Hughes69f05d22014-06-05 20:10:09 -0700620 // http://b/15439554
621 char buf[BUFSIZ];
622
623 // 1-byte character.
624 snprintf(buf, sizeof(buf), "%dx%d", 1, 2);
625 EXPECT_STREQ("1x2", buf);
626 // 2-byte character.
627 snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2);
628 EXPECT_STREQ("1¢2", buf);
629 // 3-byte character.
630 snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2);
631 EXPECT_STREQ("1€2", buf);
632 // 4-byte character.
633 snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2);
634 EXPECT_STREQ("1𤭢2", buf);
Dan Albert1aec7c12014-07-30 10:53:48 -0700635
Wally Yaua40fdbd2014-08-26 09:47:23 -0700636 uselocale(old_locale);
Dan Albert1aec7c12014-07-30 10:53:48 -0700637 freelocale(cloc);
Elliott Hughes69f05d22014-06-05 20:10:09 -0700638}
639
Elliott Hughes43f7c872016-02-05 11:18:41 -0800640static void* snprintf_small_stack_fn(void*) {
641 // Make life (realistically) hard for ourselves by allocating our own buffer for the result.
642 char buf[PATH_MAX];
643 snprintf(buf, sizeof(buf), "/proc/%d", getpid());
644 return nullptr;
645}
646
647TEST(STDIO_TEST, snprintf_small_stack) {
648 // Is it safe to call snprintf on a thread with a small stack?
649 // (The snprintf implementation puts some pretty large buffers on the stack.)
650 pthread_attr_t a;
651 ASSERT_EQ(0, pthread_attr_init(&a));
652 ASSERT_EQ(0, pthread_attr_setstacksize(&a, PTHREAD_STACK_MIN));
653
654 pthread_t t;
655 ASSERT_EQ(0, pthread_create(&t, &a, snprintf_small_stack_fn, nullptr));
656 ASSERT_EQ(0, pthread_join(t, nullptr));
657}
658
Elliott Hughes8200e552016-02-05 21:57:37 -0800659TEST(STDIO_TEST, snprintf_asterisk_overflow) {
660 char buf[128];
661 ASSERT_EQ(5, snprintf(buf, sizeof(buf), "%.*s%c", 4, "hello world", '!'));
662 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX/2, "hello world", '!'));
663 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX-1, "hello world", '!'));
664 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX, "hello world", '!'));
665 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", -1, "hello world", '!'));
666
667 // INT_MAX-1, INT_MAX, INT_MAX+1.
668 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483646s%c", "hello world", '!'));
669 ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483647s%c", "hello world", '!'));
670 ASSERT_EQ(-1, snprintf(buf, sizeof(buf), "%.2147483648s%c", "hello world", '!'));
671 ASSERT_EQ(ENOMEM, errno);
672}
673
Elliott Hughes70715da2016-08-01 16:35:17 -0700674TEST(STDIO_TEST, fprintf) {
675 TemporaryFile tf;
676
677 FILE* tfile = fdopen(tf.fd, "r+");
678 ASSERT_TRUE(tfile != nullptr);
679
680 ASSERT_EQ(7, fprintf(tfile, "%d %s", 123, "abc"));
681 AssertFileIs(tfile, "123 abc");
682 fclose(tfile);
683}
684
Christopher Ferris13f26a72016-01-13 13:47:58 -0800685TEST(STDIO_TEST, fprintf_failures_7229520) {
Elliott Hughes69f05d22014-06-05 20:10:09 -0700686 // http://b/7229520
Elliott Hughesc9244bd2014-05-14 13:31:35 -0700687 FILE* fp;
688
689 // Unbuffered case where the fprintf(3) itself fails.
690 ASSERT_NE(nullptr, fp = tmpfile());
691 setbuf(fp, NULL);
692 ASSERT_EQ(4, fprintf(fp, "epic"));
693 ASSERT_EQ(0, close(fileno(fp)));
694 ASSERT_EQ(-1, fprintf(fp, "fail"));
695 ASSERT_EQ(-1, fclose(fp));
696
697 // Buffered case where we won't notice until the fclose(3).
698 // It's likely this is what was actually seen in http://b/7229520,
699 // and that expecting fprintf to fail is setting yourself up for
700 // disappointment. Remember to check fclose(3)'s return value, kids!
701 ASSERT_NE(nullptr, fp = tmpfile());
702 ASSERT_EQ(4, fprintf(fp, "epic"));
703 ASSERT_EQ(0, close(fileno(fp)));
704 ASSERT_EQ(4, fprintf(fp, "fail"));
705 ASSERT_EQ(-1, fclose(fp));
706}
707
Christopher Ferris13f26a72016-01-13 13:47:58 -0800708TEST(STDIO_TEST, popen) {
Elliott Hughes6b3f49a2013-03-06 16:20:55 -0800709 FILE* fp = popen("cat /proc/version", "r");
710 ASSERT_TRUE(fp != NULL);
711
712 char buf[16];
713 char* s = fgets(buf, sizeof(buf), fp);
714 buf[13] = '\0';
715 ASSERT_STREQ("Linux version", s);
716
717 ASSERT_EQ(0, pclose(fp));
718}
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700719
Christopher Ferris13f26a72016-01-13 13:47:58 -0800720TEST(STDIO_TEST, getc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700721 FILE* fp = fopen("/proc/version", "r");
722 ASSERT_TRUE(fp != NULL);
723 ASSERT_EQ('L', getc(fp));
724 ASSERT_EQ('i', getc(fp));
725 ASSERT_EQ('n', getc(fp));
726 ASSERT_EQ('u', getc(fp));
727 ASSERT_EQ('x', getc(fp));
728 fclose(fp);
729}
730
Christopher Ferris13f26a72016-01-13 13:47:58 -0800731TEST(STDIO_TEST, putc) {
Elliott Hughes6b05c8e2013-04-11 13:54:48 -0700732 FILE* fp = fopen("/proc/version", "r");
733 ASSERT_TRUE(fp != NULL);
734 ASSERT_EQ(EOF, putc('x', fp));
735 fclose(fp);
736}
Elliott Hughes603332f2014-03-12 17:10:41 -0700737
Elliott Hughes7f0849f2016-08-26 16:17:17 -0700738TEST(STDIO_TEST, sscanf_swscanf) {
739 struct stuff {
740 char s1[123];
741 int i1;
742 double d1;
743 float f1;
744 char s2[123];
745
746 void Check() {
747 ASSERT_STREQ("hello", s1);
748 ASSERT_EQ(123, i1);
749 ASSERT_DOUBLE_EQ(1.23, d1);
750 ASSERT_FLOAT_EQ(9.0f, f1);
751 ASSERT_STREQ("world", s2);
752 }
753 } s;
754
755 memset(&s, 0, sizeof(s));
756 ASSERT_EQ(5, sscanf(" hello 123 1.23 0x1.2p3 world",
757 "%s %i %lf %f %s",
758 s.s1, &s.i1, &s.d1, &s.f1, s.s2));
759 s.Check();
760
761 memset(&s, 0, sizeof(s));
762 ASSERT_EQ(5, swscanf(L" hello 123 1.23 0x1.2p3 world",
763 L"%s %i %lf %f %s",
764 s.s1, &s.i1, &s.d1, &s.f1, s.s2));
765 s.Check();
Elliott Hughes603332f2014-03-12 17:10:41 -0700766}
Elliott Hughes53b24382014-05-02 18:29:25 -0700767
Christopher Ferris13f26a72016-01-13 13:47:58 -0800768TEST(STDIO_TEST, cantwrite_EBADF) {
Elliott Hughes53b24382014-05-02 18:29:25 -0700769 // If we open a file read-only...
770 FILE* fp = fopen("/proc/version", "r");
771
772 // ...all attempts to write to that file should return failure.
773
774 // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
775 // glibc gets the wide-character functions wrong.
776
777 errno = 0;
778 EXPECT_EQ(EOF, putc('x', fp));
779 EXPECT_EQ(EBADF, errno);
780
781 errno = 0;
782 EXPECT_EQ(EOF, fprintf(fp, "hello"));
783 EXPECT_EQ(EBADF, errno);
784
785 errno = 0;
786 EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
Elliott Hughes063525c2014-05-13 11:19:57 -0700787#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -0700788 EXPECT_EQ(EBADF, errno);
789#endif
790
791 errno = 0;
Elliott Hughes53b24382014-05-02 18:29:25 -0700792 EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
793 EXPECT_EQ(EBADF, errno);
794
795 errno = 0;
796 EXPECT_EQ(EOF, fputs("hello", fp));
797 EXPECT_EQ(EBADF, errno);
798
799 errno = 0;
800 EXPECT_EQ(WEOF, fputwc(L'x', fp));
Elliott Hughes063525c2014-05-13 11:19:57 -0700801#if defined(__BIONIC__)
Elliott Hughes53b24382014-05-02 18:29:25 -0700802 EXPECT_EQ(EBADF, errno);
803#endif
804}
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100805
806// Tests that we can only have a consistent and correct fpos_t when using
807// f*pos functions (i.e. fpos doesn't get inside a multi byte character).
Christopher Ferris13f26a72016-01-13 13:47:58 -0800808TEST(STDIO_TEST, consistent_fpos_t) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100809 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
810 uselocale(LC_GLOBAL_LOCALE);
811
812 FILE* fp = tmpfile();
813 ASSERT_TRUE(fp != NULL);
814
815 wchar_t mb_one_bytes = L'h';
816 wchar_t mb_two_bytes = 0x00a2;
817 wchar_t mb_three_bytes = 0x20ac;
818 wchar_t mb_four_bytes = 0x24b62;
819
820 // Write to file.
821 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp)));
822 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
823 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
824 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
825
826 rewind(fp);
827
828 // Record each character position.
829 fpos_t pos1;
830 fpos_t pos2;
831 fpos_t pos3;
832 fpos_t pos4;
833 fpos_t pos5;
834 EXPECT_EQ(0, fgetpos(fp, &pos1));
835 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
836 EXPECT_EQ(0, fgetpos(fp, &pos2));
837 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
838 EXPECT_EQ(0, fgetpos(fp, &pos3));
839 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
840 EXPECT_EQ(0, fgetpos(fp, &pos4));
841 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
842 EXPECT_EQ(0, fgetpos(fp, &pos5));
843
Elliott Hughes063525c2014-05-13 11:19:57 -0700844#if defined(__BIONIC__)
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100845 // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD
846 // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In
847 // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE
848 // structure.
849 ASSERT_EQ(0, static_cast<off_t>(pos1));
850 ASSERT_EQ(1, static_cast<off_t>(pos2));
851 ASSERT_EQ(3, static_cast<off_t>(pos3));
852 ASSERT_EQ(6, static_cast<off_t>(pos4));
853 ASSERT_EQ(10, static_cast<off_t>(pos5));
854#endif
855
856 // Exercise back and forth movements of the position.
857 ASSERT_EQ(0, fsetpos(fp, &pos2));
858 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
859 ASSERT_EQ(0, fsetpos(fp, &pos1));
860 ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
861 ASSERT_EQ(0, fsetpos(fp, &pos4));
862 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
863 ASSERT_EQ(0, fsetpos(fp, &pos3));
864 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
865 ASSERT_EQ(0, fsetpos(fp, &pos5));
866 ASSERT_EQ(WEOF, fgetwc(fp));
867
868 fclose(fp);
869}
870
871// Exercise the interaction between fpos and seek.
Christopher Ferris13f26a72016-01-13 13:47:58 -0800872TEST(STDIO_TEST, fpos_t_and_seek) {
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100873 ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
874 uselocale(LC_GLOBAL_LOCALE);
875
Calin Juravle9b95ea92014-05-14 17:07:10 +0100876 // In glibc-2.16 fseek doesn't work properly in wide mode
877 // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is
878 // to close and re-open the file. We do it in order to make the test pass
879 // with all glibcs.
880
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100881 TemporaryFile tf;
882 FILE* fp = fdopen(tf.fd, "w+");
883 ASSERT_TRUE(fp != NULL);
884
885 wchar_t mb_two_bytes = 0x00a2;
886 wchar_t mb_three_bytes = 0x20ac;
887 wchar_t mb_four_bytes = 0x24b62;
888
889 // Write to file.
890 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
891 ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
892 ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
893
894 fflush(fp);
895 fclose(fp);
896
897 fp = fopen(tf.filename, "r");
898 ASSERT_TRUE(fp != NULL);
899
900 // Store a valid position.
901 fpos_t mb_two_bytes_pos;
902 ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos));
903
904 // Move inside mb_four_bytes with fseek.
905 long offset_inside_mb = 6;
906 ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET));
907
908 // Store the "inside multi byte" position.
909 fpos_t pos_inside_mb;
910 ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb));
Elliott Hughes063525c2014-05-13 11:19:57 -0700911#if defined(__BIONIC__)
912 ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb));
913#endif
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100914
915 // Reading from within a byte should produce an error.
916 ASSERT_EQ(WEOF, fgetwc(fp));
917 ASSERT_EQ(EILSEQ, errno);
918
919 // Reverting to a valid position should work.
920 ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos));
921 ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
922
923 // Moving withing a multi byte with fsetpos should work but reading should
924 // produce an error.
925 ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb));
926 ASSERT_EQ(WEOF, fgetwc(fp));
927 ASSERT_EQ(EILSEQ, errno);
928
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700929 ASSERT_EQ(0, fclose(fp));
Calin Juravle03e4ebe2014-05-08 14:42:06 +0100930}
Elliott Hughes6b841db2014-08-20 16:10:49 -0700931
Christopher Ferris13f26a72016-01-13 13:47:58 -0800932TEST(STDIO_TEST, fmemopen) {
Elliott Hughes6b841db2014-08-20 16:10:49 -0700933 char buf[16];
934 memset(buf, 0, sizeof(buf));
935 FILE* fp = fmemopen(buf, sizeof(buf), "r+");
936 ASSERT_EQ('<', fputc('<', fp));
937 ASSERT_NE(EOF, fputs("abc>\n", fp));
938 fflush(fp);
939
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700940 // We wrote to the buffer...
Elliott Hughes6b841db2014-08-20 16:10:49 -0700941 ASSERT_STREQ("<abc>\n", buf);
942
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700943 // And can read back from the file.
Elliott Hughes70715da2016-08-01 16:35:17 -0700944 AssertFileIs(fp, "<abc>\n", true);
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700945 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -0700946}
947
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700948TEST(STDIO_TEST, fmemopen_nullptr) {
Elliott Hughes6b841db2014-08-20 16:10:49 -0700949 FILE* fp = fmemopen(nullptr, 128, "r+");
950 ASSERT_NE(EOF, fputs("xyz\n", fp));
951
Elliott Hughes70715da2016-08-01 16:35:17 -0700952 AssertFileIs(fp, "xyz\n", true);
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700953 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -0700954}
955
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700956TEST(STDIO_TEST, fmemopen_trailing_NUL_byte) {
957 FILE* fp;
958 char buf[8];
959
960 // POSIX: "When a stream open for writing is flushed or closed, a null byte
961 // shall be written at the current position or at the end of the buffer,
962 // depending on the size of the contents."
963 memset(buf, 'x', sizeof(buf));
964 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w"));
965 // Even with nothing written (and not in truncate mode), we'll flush a NUL...
966 ASSERT_EQ(0, fflush(fp));
967 EXPECT_EQ("\0xxxxxxx"s, std::string(buf, buf + sizeof(buf)));
968 // Now write and check that the NUL moves along with our writes...
969 ASSERT_NE(EOF, fputs("hello", fp));
970 ASSERT_EQ(0, fflush(fp));
971 EXPECT_EQ("hello\0xx"s, std::string(buf, buf + sizeof(buf)));
972 ASSERT_NE(EOF, fputs("wo", fp));
973 ASSERT_EQ(0, fflush(fp));
974 EXPECT_EQ("hellowo\0"s, std::string(buf, buf + sizeof(buf)));
975 ASSERT_EQ(0, fclose(fp));
976
977 // "If a stream open for update is flushed or closed and the last write has
978 // advanced the current buffer size, a null byte shall be written at the end
979 // of the buffer if it fits."
980 memset(buf, 'x', sizeof(buf));
981 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r+"));
982 // Nothing written yet, so no advance...
983 ASSERT_EQ(0, fflush(fp));
984 EXPECT_EQ("xxxxxxxx"s, std::string(buf, buf + sizeof(buf)));
985 ASSERT_NE(EOF, fputs("hello", fp));
986 ASSERT_EQ(0, fclose(fp));
987}
988
989TEST(STDIO_TEST, fmemopen_size) {
990 FILE* fp;
Elliott Hughes6b841db2014-08-20 16:10:49 -0700991 char buf[16];
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700992 memset(buf, 'x', sizeof(buf));
Elliott Hughes6b841db2014-08-20 16:10:49 -0700993
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700994 // POSIX: "The stream shall also maintain the size of the current buffer
995 // contents; use of fseek() or fseeko() on the stream with SEEK_END shall
996 // seek relative to this size."
Elliott Hughes6b841db2014-08-20 16:10:49 -0700997
Elliott Hughes3a4c4542017-07-19 17:20:24 -0700998 // "For modes r and r+ the size shall be set to the value given by the size
999 // argument."
1000 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "r"));
1001 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1002 EXPECT_EQ(16, ftell(fp));
1003 EXPECT_EQ(16, ftello(fp));
1004 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1005 EXPECT_EQ(16, ftell(fp));
1006 EXPECT_EQ(16, ftello(fp));
1007 ASSERT_EQ(0, fclose(fp));
1008 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "r+"));
1009 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1010 EXPECT_EQ(16, ftell(fp));
1011 EXPECT_EQ(16, ftello(fp));
1012 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1013 EXPECT_EQ(16, ftell(fp));
1014 EXPECT_EQ(16, ftello(fp));
1015 ASSERT_EQ(0, fclose(fp));
1016
1017 // "For modes w and w+ the initial size shall be zero..."
1018 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w"));
1019 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1020 EXPECT_EQ(0, ftell(fp));
1021 EXPECT_EQ(0, ftello(fp));
1022 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1023 EXPECT_EQ(0, ftell(fp));
1024 EXPECT_EQ(0, ftello(fp));
1025 ASSERT_EQ(0, fclose(fp));
1026 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w+"));
1027 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1028 EXPECT_EQ(0, ftell(fp));
1029 EXPECT_EQ(0, ftello(fp));
1030 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1031 EXPECT_EQ(0, ftell(fp));
1032 EXPECT_EQ(0, ftello(fp));
1033 ASSERT_EQ(0, fclose(fp));
1034
1035 // "...and for modes a and a+ the initial size shall be:
1036 // 1. Zero, if buf is a null pointer
1037 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "a"));
1038 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1039 EXPECT_EQ(0, ftell(fp));
1040 EXPECT_EQ(0, ftello(fp));
1041 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1042 EXPECT_EQ(0, ftell(fp));
1043 EXPECT_EQ(0, ftello(fp));
1044 ASSERT_EQ(0, fclose(fp));
1045 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "a+"));
1046 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1047 EXPECT_EQ(0, ftell(fp));
1048 EXPECT_EQ(0, ftello(fp));
1049 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1050 EXPECT_EQ(0, ftell(fp));
1051 EXPECT_EQ(0, ftello(fp));
1052 ASSERT_EQ(0, fclose(fp));
1053
1054 // 2. The position of the first null byte in the buffer, if one is found
1055 memset(buf, 'x', sizeof(buf));
1056 buf[3] = '\0';
1057 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a"));
1058 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1059 EXPECT_EQ(3, ftell(fp));
1060 EXPECT_EQ(3, ftello(fp));
1061 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1062 EXPECT_EQ(3, ftell(fp));
1063 EXPECT_EQ(3, ftello(fp));
1064 ASSERT_EQ(0, fclose(fp));
1065 memset(buf, 'x', sizeof(buf));
1066 buf[3] = '\0';
1067 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a+"));
1068 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1069 EXPECT_EQ(3, ftell(fp));
1070 EXPECT_EQ(3, ftello(fp));
1071 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1072 EXPECT_EQ(3, ftell(fp));
1073 EXPECT_EQ(3, ftello(fp));
1074 ASSERT_EQ(0, fclose(fp));
1075
1076 // 3. The value of the size argument, if buf is not a null pointer and no
1077 // null byte is found.
1078 memset(buf, 'x', sizeof(buf));
1079 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a"));
1080 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1081 EXPECT_EQ(16, ftell(fp));
1082 EXPECT_EQ(16, ftello(fp));
1083 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1084 EXPECT_EQ(16, ftell(fp));
1085 EXPECT_EQ(16, ftello(fp));
1086 ASSERT_EQ(0, fclose(fp));
1087 memset(buf, 'x', sizeof(buf));
1088 ASSERT_NE(nullptr, fp = fmemopen(buf, 16, "a+"));
1089 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1090 EXPECT_EQ(16, ftell(fp));
1091 EXPECT_EQ(16, ftello(fp));
1092 ASSERT_EQ(0, fseeko(fp, 0, SEEK_END));
1093 EXPECT_EQ(16, ftell(fp));
1094 EXPECT_EQ(16, ftello(fp));
1095 ASSERT_EQ(0, fclose(fp));
1096}
1097
1098TEST(STDIO_TEST, fmemopen_SEEK_END) {
1099 // fseek SEEK_END is relative to the current string length, not the buffer size.
1100 FILE* fp;
1101 char buf[8];
1102 memset(buf, 'x', sizeof(buf));
1103 strcpy(buf, "str");
1104 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1105 ASSERT_NE(EOF, fputs("string", fp));
1106 EXPECT_EQ(0, fseek(fp, 0, SEEK_END));
1107 EXPECT_EQ(static_cast<long>(strlen("string")), ftell(fp));
1108 EXPECT_EQ(static_cast<off_t>(strlen("string")), ftello(fp));
1109 EXPECT_EQ(0, fclose(fp));
1110
1111 // glibc < 2.22 interpreted SEEK_END the wrong way round (subtracting rather
1112 // than adding).
1113 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1114 ASSERT_NE(EOF, fputs("54321", fp));
1115 EXPECT_EQ(0, fseek(fp, -2, SEEK_END));
1116 EXPECT_EQ('2', fgetc(fp));
1117 EXPECT_EQ(0, fclose(fp));
1118}
1119
1120TEST(STDIO_TEST, fmemopen_seek_invalid) {
1121 char buf[8];
1122 memset(buf, 'x', sizeof(buf));
1123 FILE* fp = fmemopen(buf, sizeof(buf), "w");
1124 ASSERT_TRUE(fp != nullptr);
1125
1126 // POSIX: "An attempt to seek ... to a negative position or to a position
1127 // larger than the buffer size given in the size argument shall fail."
1128 // (There's no mention of what errno should be set to, and glibc doesn't
1129 // set errno in any of these cases.)
1130 EXPECT_EQ(-1, fseek(fp, -2, SEEK_SET));
1131 EXPECT_EQ(-1, fseeko(fp, -2, SEEK_SET));
1132 EXPECT_EQ(-1, fseek(fp, sizeof(buf) + 1, SEEK_SET));
1133 EXPECT_EQ(-1, fseeko(fp, sizeof(buf) + 1, SEEK_SET));
1134}
1135
1136TEST(STDIO_TEST, fmemopen_read_EOF) {
1137 // POSIX: "A read operation on the stream shall not advance the current
1138 // buffer position beyond the current buffer size."
1139 char buf[8];
1140 memset(buf, 'x', sizeof(buf));
1141 FILE* fp = fmemopen(buf, sizeof(buf), "r");
1142 ASSERT_TRUE(fp != nullptr);
1143 char buf2[BUFSIZ];
1144 ASSERT_EQ(8U, fread(buf2, 1, sizeof(buf2), fp));
1145 // POSIX: "Reaching the buffer size in a read operation shall count as
1146 // end-of-file.
1147 ASSERT_TRUE(feof(fp));
1148 ASSERT_EQ(EOF, fgetc(fp));
1149 ASSERT_EQ(0, fclose(fp));
1150}
1151
1152TEST(STDIO_TEST, fmemopen_read_null_bytes) {
1153 // POSIX: "Null bytes in the buffer shall have no special meaning for reads."
1154 char buf[] = "h\0e\0l\0l\0o";
1155 FILE* fp = fmemopen(buf, sizeof(buf), "r");
1156 ASSERT_TRUE(fp != nullptr);
1157 ASSERT_EQ('h', fgetc(fp));
1158 ASSERT_EQ(0, fgetc(fp));
1159 ASSERT_EQ('e', fgetc(fp));
1160 ASSERT_EQ(0, fgetc(fp));
1161 ASSERT_EQ('l', fgetc(fp));
1162 ASSERT_EQ(0, fgetc(fp));
1163 // POSIX: "The read operation shall start at the current buffer position of
1164 // the stream."
1165 char buf2[8];
1166 memset(buf2, 'x', sizeof(buf2));
1167 ASSERT_EQ(4U, fread(buf2, 1, sizeof(buf2), fp));
1168 ASSERT_EQ('l', buf2[0]);
1169 ASSERT_EQ(0, buf2[1]);
1170 ASSERT_EQ('o', buf2[2]);
1171 ASSERT_EQ(0, buf2[3]);
1172 for (size_t i = 4; i < sizeof(buf2); ++i) ASSERT_EQ('x', buf2[i]) << i;
1173 ASSERT_TRUE(feof(fp));
1174 ASSERT_EQ(0, fclose(fp));
1175}
1176
1177TEST(STDIO_TEST, fmemopen_write) {
1178 FILE* fp;
1179 char buf[8];
1180
1181 // POSIX: "A write operation shall start either at the current position of
1182 // the stream (if mode has not specified 'a' as the first character)..."
1183 memset(buf, 'x', sizeof(buf));
1184 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r+"));
1185 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1186 ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
1187 ASSERT_EQ(' ', fputc(' ', fp));
1188 EXPECT_EQ("xx xxxxx", std::string(buf, buf + sizeof(buf)));
1189 ASSERT_EQ(0, fclose(fp));
1190
1191 // "...or at the current size of the stream (if mode had 'a' as the first
1192 // character)." (See the fmemopen_size test for what "size" means, but for
1193 // mode "a", it's the first NUL byte.)
1194 memset(buf, 'x', sizeof(buf));
1195 buf[3] = '\0';
1196 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a+"));
1197 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1198 ASSERT_EQ(' ', fputc(' ', fp));
1199 EXPECT_EQ("xxx \0xxx"s, std::string(buf, buf + sizeof(buf)));
1200 ASSERT_EQ(0, fclose(fp));
1201
1202 // "If the current position at the end of the write is larger than the
1203 // current buffer size, the current buffer size shall be set to the current
1204 // position." (See the fmemopen_size test for what "size" means, but to
1205 // query it we SEEK_END with offset 0, and then ftell.)
1206 memset(buf, 'x', sizeof(buf));
1207 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w+"));
1208 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1209 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1210 EXPECT_EQ(0, ftell(fp));
1211 ASSERT_EQ(' ', fputc(' ', fp));
1212 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1213 EXPECT_EQ(1, ftell(fp));
1214 ASSERT_NE(EOF, fputs("123", fp));
1215 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1216 EXPECT_EQ(4, ftell(fp));
1217 EXPECT_EQ(" 123\0xxx"s, std::string(buf, buf + sizeof(buf)));
1218 ASSERT_EQ(0, fclose(fp));
1219}
1220
1221TEST(STDIO_TEST, fmemopen_write_EOF) {
1222 // POSIX: "A write operation on the stream shall not advance the current
1223 // buffer size beyond the size given in the size argument."
1224 FILE* fp;
1225
1226 // Scalar writes...
1227 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 4, "w"));
1228 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1229 ASSERT_EQ('x', fputc('x', fp));
1230 ASSERT_EQ('x', fputc('x', fp));
1231 ASSERT_EQ('x', fputc('x', fp));
1232 ASSERT_EQ(EOF, fputc('x', fp)); // Only 3 fit because of the implicit NUL.
1233 ASSERT_EQ(0, fclose(fp));
1234
1235 // Vector writes...
1236 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 4, "w"));
1237 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1238 ASSERT_EQ(3U, fwrite("xxxx", 1, 4, fp));
1239 ASSERT_EQ(0, fclose(fp));
1240}
1241
1242TEST(STDIO_TEST, fmemopen_initial_position) {
1243 // POSIX: "The ... current position in the buffer ... shall be initially
1244 // set to either the beginning of the buffer (for r and w modes) ..."
1245 char buf[] = "hello\0world";
1246 FILE* fp;
1247 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "r"));
1248 EXPECT_EQ(0L, ftell(fp));
1249 EXPECT_EQ(0, fclose(fp));
1250 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "w"));
1251 EXPECT_EQ(0L, ftell(fp));
1252 EXPECT_EQ(0, fclose(fp));
1253 buf[0] = 'h'; // (Undo the effects of the above.)
1254
1255 // POSIX: "...or to the first null byte in the buffer (for a modes)."
1256 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1257 EXPECT_EQ(5L, ftell(fp));
1258 EXPECT_EQ(0, fclose(fp));
1259
1260 // POSIX: "If no null byte is found in append mode, the initial position
1261 // shall be set to one byte after the end of the buffer."
1262 memset(buf, 'x', sizeof(buf));
1263 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1264 EXPECT_EQ(static_cast<long>(sizeof(buf)), ftell(fp));
1265 EXPECT_EQ(0, fclose(fp));
1266}
1267
1268TEST(STDIO_TEST, fmemopen_initial_position_allocated) {
1269 // POSIX: "If buf is a null pointer, the initial position shall always be
1270 // set to the beginning of the buffer."
1271 FILE* fp = fmemopen(nullptr, 128, "a+");
1272 ASSERT_TRUE(fp != nullptr);
1273 EXPECT_EQ(0L, ftell(fp));
1274 EXPECT_EQ(0L, fseek(fp, 0, SEEK_SET));
1275 EXPECT_EQ(0, fclose(fp));
1276}
1277
1278TEST(STDIO_TEST, fmemopen_zero_length) {
1279 // POSIX says it's up to the implementation whether or not you can have a
1280 // zero-length buffer (but "A future version of this standard may require
1281 // support of zero-length buffer streams explicitly"). BSD and glibc < 2.22
1282 // agreed that you couldn't, but glibc >= 2.22 allows it for consistency.
1283 FILE* fp;
1284 char buf[16];
1285 ASSERT_NE(nullptr, fp = fmemopen(buf, 0, "r+"));
1286 ASSERT_EQ(EOF, fgetc(fp));
1287 ASSERT_TRUE(feof(fp));
1288 ASSERT_EQ(0, fclose(fp));
1289 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 0, "r+"));
1290 ASSERT_EQ(EOF, fgetc(fp));
1291 ASSERT_TRUE(feof(fp));
1292 ASSERT_EQ(0, fclose(fp));
1293
1294 ASSERT_NE(nullptr, fp = fmemopen(buf, 0, "w+"));
1295 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1296 ASSERT_EQ(EOF, fputc('x', fp));
1297 ASSERT_EQ(0, fclose(fp));
1298 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 0, "w+"));
1299 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1300 ASSERT_EQ(EOF, fputc('x', fp));
1301 ASSERT_EQ(0, fclose(fp));
1302}
1303
1304TEST(STDIO_TEST, fmemopen_write_only_allocated) {
1305 // POSIX says fmemopen "may fail if the mode argument does not include a '+'".
1306 // BSD fails, glibc doesn't. We side with the more lenient.
1307 FILE* fp;
1308 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "r"));
1309 ASSERT_EQ(0, fclose(fp));
1310 ASSERT_NE(nullptr, fp = fmemopen(nullptr, 16, "w"));
1311 ASSERT_EQ(0, fclose(fp));
1312}
1313
1314TEST(STDIO_TEST, fmemopen_fileno) {
1315 // There's no fd backing an fmemopen FILE*.
1316 FILE* fp = fmemopen(nullptr, 16, "r");
1317 ASSERT_TRUE(fp != nullptr);
Elliott Hughes6b841db2014-08-20 16:10:49 -07001318 errno = 0;
Elliott Hughes3a4c4542017-07-19 17:20:24 -07001319 ASSERT_EQ(-1, fileno(fp));
1320 ASSERT_EQ(EBADF, errno);
1321 ASSERT_EQ(0, fclose(fp));
1322}
1323
1324TEST(STDIO_TEST, fmemopen_append_after_seek) {
1325 // In BSD and glibc < 2.22, append mode didn't force writes to append if
1326 // there had been an intervening seek.
1327
1328 FILE* fp;
1329 char buf[] = "hello\0world";
1330 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a"));
1331 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1332 ASSERT_EQ(0, fseek(fp, 0, SEEK_SET));
1333 ASSERT_NE(EOF, fputc('!', fp));
1334 EXPECT_EQ("hello!\0orld\0"s, std::string(buf, buf + sizeof(buf)));
1335 ASSERT_EQ(0, fclose(fp));
1336
1337 memcpy(buf, "hello\0world", sizeof(buf));
1338 ASSERT_NE(nullptr, fp = fmemopen(buf, sizeof(buf), "a+"));
1339 setbuf(fp, nullptr); // Turn off buffering so we can see what's happening as it happens.
1340 ASSERT_EQ(0, fseek(fp, 0, SEEK_SET));
1341 ASSERT_NE(EOF, fputc('!', fp));
1342 EXPECT_EQ("hello!\0orld\0"s, std::string(buf, buf + sizeof(buf)));
1343 ASSERT_EQ(0, fclose(fp));
Elliott Hughes6b841db2014-08-20 16:10:49 -07001344}
1345
Christopher Ferris13f26a72016-01-13 13:47:58 -08001346TEST(STDIO_TEST, open_memstream) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001347 char* p = nullptr;
1348 size_t size = 0;
1349 FILE* fp = open_memstream(&p, &size);
1350 ASSERT_NE(EOF, fputs("hello, world!", fp));
1351 fclose(fp);
1352
1353 ASSERT_STREQ("hello, world!", p);
1354 ASSERT_EQ(strlen("hello, world!"), size);
1355 free(p);
1356}
1357
Christopher Ferris13f26a72016-01-13 13:47:58 -08001358TEST(STDIO_TEST, open_memstream_EINVAL) {
Elliott Hughes6b841db2014-08-20 16:10:49 -07001359#if defined(__BIONIC__)
1360 char* p;
1361 size_t size;
1362
1363 // Invalid buffer.
1364 errno = 0;
1365 ASSERT_EQ(nullptr, open_memstream(nullptr, &size));
1366 ASSERT_EQ(EINVAL, errno);
1367
1368 // Invalid size.
1369 errno = 0;
1370 ASSERT_EQ(nullptr, open_memstream(&p, nullptr));
1371 ASSERT_EQ(EINVAL, errno);
1372#else
Elliott Hughes9677fab2016-01-25 15:50:59 -08001373 GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
Elliott Hughes6b841db2014-08-20 16:10:49 -07001374#endif
1375}
Elliott Hughes31165ed2014-09-23 17:34:29 -07001376
Christopher Ferris13f26a72016-01-13 13:47:58 -08001377TEST(STDIO_TEST, fdopen_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07001378 int fd = open("/proc/version", O_RDONLY);
1379 ASSERT_TRUE(fd != -1);
1380
1381 // This fd doesn't have O_CLOEXEC...
1382 int flags = fcntl(fd, F_GETFD);
1383 ASSERT_TRUE(flags != -1);
1384 ASSERT_EQ(0, flags & FD_CLOEXEC);
1385
1386 FILE* fp = fdopen(fd, "re");
1387 ASSERT_TRUE(fp != NULL);
1388
1389 // ...but the new one does.
1390 flags = fcntl(fileno(fp), F_GETFD);
1391 ASSERT_TRUE(flags != -1);
1392 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
1393
1394 fclose(fp);
1395 close(fd);
1396}
1397
Christopher Ferris13f26a72016-01-13 13:47:58 -08001398TEST(STDIO_TEST, freopen_CLOEXEC) {
Elliott Hughes31165ed2014-09-23 17:34:29 -07001399 FILE* fp = fopen("/proc/version", "r");
1400 ASSERT_TRUE(fp != NULL);
1401
1402 // This FILE* doesn't have O_CLOEXEC...
1403 int flags = fcntl(fileno(fp), F_GETFD);
1404 ASSERT_TRUE(flags != -1);
1405 ASSERT_EQ(0, flags & FD_CLOEXEC);
1406
1407 fp = freopen("/proc/version", "re", fp);
1408
1409 // ...but the new one does.
1410 flags = fcntl(fileno(fp), F_GETFD);
1411 ASSERT_TRUE(flags != -1);
1412 ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
1413
1414 fclose(fp);
1415}
Elliott Hughes20841a12014-12-01 16:13:30 -08001416
Elliott Hughesf226ee52016-02-03 11:24:28 -08001417TEST(STDIO_TEST, fopen64_freopen64) {
1418 FILE* fp = fopen64("/proc/version", "r");
1419 ASSERT_TRUE(fp != nullptr);
1420 fp = freopen64("/proc/version", "re", fp);
1421 ASSERT_TRUE(fp != nullptr);
1422 fclose(fp);
1423}
1424
Elliott Hughes20841a12014-12-01 16:13:30 -08001425// https://code.google.com/p/android/issues/detail?id=81155
1426// http://b/18556607
Christopher Ferris13f26a72016-01-13 13:47:58 -08001427TEST(STDIO_TEST, fread_unbuffered_pathological_performance) {
Elliott Hughes20841a12014-12-01 16:13:30 -08001428 FILE* fp = fopen("/dev/zero", "r");
1429 ASSERT_TRUE(fp != NULL);
1430
1431 // Make this stream unbuffered.
1432 setvbuf(fp, 0, _IONBF, 0);
1433
1434 char buf[65*1024];
1435 memset(buf, 0xff, sizeof(buf));
1436
1437 time_t t0 = time(NULL);
1438 for (size_t i = 0; i < 1024; ++i) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001439 ASSERT_EQ(1U, fread(buf, 64*1024, 1, fp));
Elliott Hughes20841a12014-12-01 16:13:30 -08001440 }
1441 time_t t1 = time(NULL);
1442
1443 fclose(fp);
1444
1445 // 1024 64KiB reads should have been very quick.
1446 ASSERT_LE(t1 - t0, 1);
1447
1448 for (size_t i = 0; i < 64*1024; ++i) {
1449 ASSERT_EQ('\0', buf[i]);
1450 }
1451 for (size_t i = 64*1024; i < 65*1024; ++i) {
1452 ASSERT_EQ('\xff', buf[i]);
1453 }
1454}
Elliott Hughes75b99382015-01-20 11:23:50 -08001455
Christopher Ferris13f26a72016-01-13 13:47:58 -08001456TEST(STDIO_TEST, fread_EOF) {
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001457 std::string digits("0123456789");
1458 FILE* fp = fmemopen(&digits[0], digits.size(), "r");
Elliott Hughes75b99382015-01-20 11:23:50 -08001459
1460 // Try to read too much, but little enough that it still fits in the FILE's internal buffer.
1461 char buf1[4 * 4];
1462 memset(buf1, 0, sizeof(buf1));
1463 ASSERT_EQ(2U, fread(buf1, 4, 4, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001464 ASSERT_STREQ("0123456789", buf1);
Elliott Hughes75b99382015-01-20 11:23:50 -08001465 ASSERT_TRUE(feof(fp));
1466
1467 rewind(fp);
1468
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001469 // Try to read way too much so stdio tries to read more direct from the stream.
1470 char buf2[4 * 4096];
Elliott Hughes75b99382015-01-20 11:23:50 -08001471 memset(buf2, 0, sizeof(buf2));
1472 ASSERT_EQ(2U, fread(buf2, 4, 4096, fp));
Elliott Hughes0ed7e082015-01-22 15:13:38 -08001473 ASSERT_STREQ("0123456789", buf2);
Elliott Hughes75b99382015-01-20 11:23:50 -08001474 ASSERT_TRUE(feof(fp));
1475
1476 fclose(fp);
1477}
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001478
1479static void test_fread_from_write_only_stream(size_t n) {
1480 FILE* fp = fopen("/dev/null", "w");
1481 std::vector<char> buf(n, 0);
1482 errno = 0;
1483 ASSERT_EQ(0U, fread(&buf[0], n, 1, fp));
1484 ASSERT_EQ(EBADF, errno);
1485 ASSERT_TRUE(ferror(fp));
1486 ASSERT_FALSE(feof(fp));
1487 fclose(fp);
1488}
1489
Christopher Ferris13f26a72016-01-13 13:47:58 -08001490TEST(STDIO_TEST, fread_from_write_only_stream_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001491 test_fread_from_write_only_stream(1);
1492}
1493
Christopher Ferris13f26a72016-01-13 13:47:58 -08001494TEST(STDIO_TEST, fread_from_write_only_stream_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001495 test_fread_from_write_only_stream(64*1024);
1496}
1497
1498static void test_fwrite_after_fread(size_t n) {
1499 TemporaryFile tf;
1500
1501 FILE* fp = fdopen(tf.fd, "w+");
1502 ASSERT_EQ(1U, fwrite("1", 1, 1, fp));
1503 fflush(fp);
1504
1505 // We've flushed but not rewound, so there's nothing to read.
1506 std::vector<char> buf(n, 0);
1507 ASSERT_EQ(0U, fread(&buf[0], 1, buf.size(), fp));
1508 ASSERT_TRUE(feof(fp));
1509
1510 // But hitting EOF doesn't prevent us from writing...
1511 errno = 0;
Elliott Hughes9677fab2016-01-25 15:50:59 -08001512 ASSERT_EQ(1U, fwrite("2", 1, 1, fp)) << strerror(errno);
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001513
1514 // And if we rewind, everything's there.
1515 rewind(fp);
1516 ASSERT_EQ(2U, fread(&buf[0], 1, buf.size(), fp));
1517 ASSERT_EQ('1', buf[0]);
1518 ASSERT_EQ('2', buf[1]);
1519
1520 fclose(fp);
1521}
1522
Christopher Ferris13f26a72016-01-13 13:47:58 -08001523TEST(STDIO_TEST, fwrite_after_fread_slow_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001524 test_fwrite_after_fread(16);
1525}
1526
Christopher Ferris13f26a72016-01-13 13:47:58 -08001527TEST(STDIO_TEST, fwrite_after_fread_fast_path) {
Elliott Hughese6bb5a22015-01-23 17:48:15 -08001528 test_fwrite_after_fread(64*1024);
1529}
Christopher Ferriscc9ca102015-02-27 18:22:45 -08001530
1531// http://b/19172514
Christopher Ferris13f26a72016-01-13 13:47:58 -08001532TEST(STDIO_TEST, fread_after_fseek) {
Christopher Ferriscc9ca102015-02-27 18:22:45 -08001533 TemporaryFile tf;
1534
1535 FILE* fp = fopen(tf.filename, "w+");
1536 ASSERT_TRUE(fp != nullptr);
1537
1538 char file_data[12288];
1539 for (size_t i = 0; i < 12288; i++) {
1540 file_data[i] = i;
1541 }
1542 ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp));
1543 fclose(fp);
1544
1545 fp = fopen(tf.filename, "r");
1546 ASSERT_TRUE(fp != nullptr);
1547
1548 char buffer[8192];
1549 size_t cur_location = 0;
1550 // Small read to populate internal buffer.
1551 ASSERT_EQ(100U, fread(buffer, 1, 100, fp));
1552 ASSERT_EQ(memcmp(file_data, buffer, 100), 0);
1553
1554 cur_location = static_cast<size_t>(ftell(fp));
1555 // Large read to force reading into the user supplied buffer and bypassing
1556 // the internal buffer.
1557 ASSERT_EQ(8192U, fread(buffer, 1, 8192, fp));
1558 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 8192), 0);
1559
1560 // Small backwards seek to verify fseek does not reuse the internal buffer.
Elliott Hughes9677fab2016-01-25 15:50:59 -08001561 ASSERT_EQ(0, fseek(fp, -22, SEEK_CUR)) << strerror(errno);
Christopher Ferriscc9ca102015-02-27 18:22:45 -08001562 cur_location = static_cast<size_t>(ftell(fp));
1563 ASSERT_EQ(22U, fread(buffer, 1, 22, fp));
1564 ASSERT_EQ(memcmp(file_data+cur_location, buffer, 22), 0);
1565
1566 fclose(fp);
1567}
Elliott Hughes8ab433d2015-10-09 17:57:26 -07001568
1569// https://code.google.com/p/android/issues/detail?id=184847
Christopher Ferris13f26a72016-01-13 13:47:58 -08001570TEST(STDIO_TEST, fread_EOF_184847) {
Elliott Hughes8ab433d2015-10-09 17:57:26 -07001571 TemporaryFile tf;
1572 char buf[6] = {0};
1573
1574 FILE* fw = fopen(tf.filename, "w");
1575 ASSERT_TRUE(fw != nullptr);
1576
1577 FILE* fr = fopen(tf.filename, "r");
1578 ASSERT_TRUE(fr != nullptr);
1579
1580 fwrite("a", 1, 1, fw);
1581 fflush(fw);
1582 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
1583 ASSERT_STREQ("a", buf);
1584
1585 // 'fr' is now at EOF.
1586 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
1587 ASSERT_TRUE(feof(fr));
1588
1589 // Write some more...
1590 fwrite("z", 1, 1, fw);
1591 fflush(fw);
1592
1593 // ...and check that we can read it back.
1594 // (BSD thinks that once a stream has hit EOF, it must always return EOF. SysV disagrees.)
1595 ASSERT_EQ(1U, fread(buf, 1, 1, fr));
1596 ASSERT_STREQ("z", buf);
1597
1598 // But now we're done.
1599 ASSERT_EQ(0U, fread(buf, 1, 1, fr));
1600
1601 fclose(fr);
1602 fclose(fw);
1603}
Elliott Hughes923f1652016-01-19 15:46:05 -08001604
1605TEST(STDIO_TEST, fclose_invalidates_fd) {
1606 // The typical error we're trying to help people catch involves accessing
1607 // memory after it's been freed. But we know that stdin/stdout/stderr are
1608 // special and don't get deallocated, so this test uses stdin.
1609 ASSERT_EQ(0, fclose(stdin));
1610
1611 // Even though using a FILE* after close is undefined behavior, I've closed
1612 // this bug as "WAI" too many times. We shouldn't hand out stale fds,
1613 // especially because they might actually correspond to a real stream.
1614 errno = 0;
1615 ASSERT_EQ(-1, fileno(stdin));
1616 ASSERT_EQ(EBADF, errno);
1617}
Elliott Hughes2704bd12016-01-20 17:14:53 -08001618
1619TEST(STDIO_TEST, fseek_ftell_unseekable) {
1620#if defined(__BIONIC__) // glibc has fopencookie instead.
1621 auto read_fn = [](void*, char*, int) { return -1; };
1622 FILE* fp = funopen(nullptr, read_fn, nullptr, nullptr, nullptr);
1623 ASSERT_TRUE(fp != nullptr);
1624
1625 // Check that ftell balks on an unseekable FILE*.
1626 errno = 0;
1627 ASSERT_EQ(-1, ftell(fp));
1628 ASSERT_EQ(ESPIPE, errno);
1629
1630 // SEEK_CUR is rewritten as SEEK_SET internally...
1631 errno = 0;
1632 ASSERT_EQ(-1, fseek(fp, 0, SEEK_CUR));
1633 ASSERT_EQ(ESPIPE, errno);
1634
1635 // ...so it's worth testing the direct seek path too.
1636 errno = 0;
1637 ASSERT_EQ(-1, fseek(fp, 0, SEEK_SET));
1638 ASSERT_EQ(ESPIPE, errno);
1639
1640 fclose(fp);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08001641#else
1642 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
1643#endif
1644}
1645
1646TEST(STDIO_TEST, funopen_EINVAL) {
1647#if defined(__BIONIC__)
1648 errno = 0;
1649 ASSERT_EQ(nullptr, funopen(nullptr, nullptr, nullptr, nullptr, nullptr));
1650 ASSERT_EQ(EINVAL, errno);
1651#else
1652 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
1653#endif
1654}
1655
1656TEST(STDIO_TEST, funopen_seek) {
1657#if defined(__BIONIC__)
1658 auto read_fn = [](void*, char*, int) { return -1; };
1659
1660 auto seek_fn = [](void*, fpos_t, int) -> fpos_t { return 0xfedcba12; };
1661 auto seek64_fn = [](void*, fpos64_t, int) -> fpos64_t { return 0xfedcba12345678; };
1662
1663 FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr);
1664 ASSERT_TRUE(fp != nullptr);
1665 fpos_t pos;
Elliott Hughes955426e2016-01-26 18:25:52 -08001666#if defined(__LP64__)
1667 EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno);
1668 EXPECT_EQ(0xfedcba12LL, pos);
1669#else
1670 EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno);
1671 EXPECT_EQ(EOVERFLOW, errno);
1672#endif
Elliott Hughes03e65eb2016-01-26 14:13:04 -08001673
1674 FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr);
1675 ASSERT_TRUE(fp64 != nullptr);
1676 fpos64_t pos64;
Elliott Hughes955426e2016-01-26 18:25:52 -08001677 EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno);
1678 EXPECT_EQ(0xfedcba12345678, pos64);
Elliott Hughes03e65eb2016-01-26 14:13:04 -08001679#else
1680 GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
Elliott Hughes2704bd12016-01-20 17:14:53 -08001681#endif
1682}
Elliott Hughes71288cb2016-01-22 19:22:44 -08001683
1684TEST(STDIO_TEST, lots_of_concurrent_files) {
1685 std::vector<TemporaryFile*> tfs;
1686 std::vector<FILE*> fps;
1687
1688 for (size_t i = 0; i < 256; ++i) {
1689 TemporaryFile* tf = new TemporaryFile;
1690 tfs.push_back(tf);
1691 FILE* fp = fopen(tf->filename, "w+");
1692 fps.push_back(fp);
1693 fprintf(fp, "hello %zu!\n", i);
1694 fflush(fp);
1695 }
1696
1697 for (size_t i = 0; i < 256; ++i) {
Elliott Hughes71288cb2016-01-22 19:22:44 -08001698 char expected[BUFSIZ];
1699 snprintf(expected, sizeof(expected), "hello %zu!\n", i);
Elliott Hughes71288cb2016-01-22 19:22:44 -08001700
Elliott Hughes70715da2016-08-01 16:35:17 -07001701 AssertFileIs(fps[i], expected);
Elliott Hughes71288cb2016-01-22 19:22:44 -08001702 fclose(fps[i]);
1703 delete tfs[i];
1704 }
1705}
Elliott Hughes9677fab2016-01-25 15:50:59 -08001706
1707static void AssertFileOffsetAt(FILE* fp, off64_t offset) {
1708 EXPECT_EQ(offset, ftell(fp));
1709 EXPECT_EQ(offset, ftello(fp));
Elliott Hughese4fa6e92016-02-02 22:39:15 -08001710 EXPECT_EQ(offset, ftello64(fp));
Elliott Hughes9677fab2016-01-25 15:50:59 -08001711 fpos_t pos;
1712 fpos64_t pos64;
1713 EXPECT_EQ(0, fgetpos(fp, &pos));
1714 EXPECT_EQ(0, fgetpos64(fp, &pos64));
1715#if defined(__BIONIC__)
1716 EXPECT_EQ(offset, static_cast<off64_t>(pos));
1717 EXPECT_EQ(offset, static_cast<off64_t>(pos64));
1718#else
1719 GTEST_LOG_(INFO) << "glibc's fpos_t is opaque.\n";
1720#endif
1721}
1722
1723TEST(STDIO_TEST, seek_tell_family_smoke) {
1724 TemporaryFile tf;
1725 FILE* fp = fdopen(tf.fd, "w+");
1726
1727 // Initially we should be at 0.
1728 AssertFileOffsetAt(fp, 0);
1729
1730 // Seek to offset 8192.
1731 ASSERT_EQ(0, fseek(fp, 8192, SEEK_SET));
1732 AssertFileOffsetAt(fp, 8192);
1733 fpos_t eight_k_pos;
1734 ASSERT_EQ(0, fgetpos(fp, &eight_k_pos));
1735
1736 // Seek forward another 8192...
1737 ASSERT_EQ(0, fseek(fp, 8192, SEEK_CUR));
1738 AssertFileOffsetAt(fp, 8192 + 8192);
1739 fpos64_t sixteen_k_pos64;
1740 ASSERT_EQ(0, fgetpos64(fp, &sixteen_k_pos64));
1741
1742 // Seek back 8192...
1743 ASSERT_EQ(0, fseek(fp, -8192, SEEK_CUR));
1744 AssertFileOffsetAt(fp, 8192);
1745
1746 // Since we haven't written anything, the end is also at 0.
1747 ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1748 AssertFileOffsetAt(fp, 0);
1749
1750 // Check that our fpos64_t from 16KiB works...
1751 ASSERT_EQ(0, fsetpos64(fp, &sixteen_k_pos64));
1752 AssertFileOffsetAt(fp, 8192 + 8192);
1753 // ...as does our fpos_t from 8192.
1754 ASSERT_EQ(0, fsetpos(fp, &eight_k_pos));
1755 AssertFileOffsetAt(fp, 8192);
1756
1757 // Do fseeko and fseeko64 work too?
1758 ASSERT_EQ(0, fseeko(fp, 1234, SEEK_SET));
1759 AssertFileOffsetAt(fp, 1234);
1760 ASSERT_EQ(0, fseeko64(fp, 5678, SEEK_SET));
1761 AssertFileOffsetAt(fp, 5678);
1762
1763 fclose(fp);
1764}
1765
1766TEST(STDIO_TEST, fseek_fseeko_EINVAL) {
1767 TemporaryFile tf;
1768 FILE* fp = fdopen(tf.fd, "w+");
1769
1770 // Bad whence.
1771 errno = 0;
1772 ASSERT_EQ(-1, fseek(fp, 0, 123));
1773 ASSERT_EQ(EINVAL, errno);
1774 errno = 0;
1775 ASSERT_EQ(-1, fseeko(fp, 0, 123));
1776 ASSERT_EQ(EINVAL, errno);
1777 errno = 0;
1778 ASSERT_EQ(-1, fseeko64(fp, 0, 123));
1779 ASSERT_EQ(EINVAL, errno);
1780
1781 // Bad offset.
1782 errno = 0;
1783 ASSERT_EQ(-1, fseek(fp, -1, SEEK_SET));
1784 ASSERT_EQ(EINVAL, errno);
1785 errno = 0;
1786 ASSERT_EQ(-1, fseeko(fp, -1, SEEK_SET));
1787 ASSERT_EQ(EINVAL, errno);
1788 errno = 0;
1789 ASSERT_EQ(-1, fseeko64(fp, -1, SEEK_SET));
1790 ASSERT_EQ(EINVAL, errno);
1791
1792 fclose(fp);
1793}
Elliott Hughes20788ae2016-06-09 15:16:32 -07001794
1795TEST(STDIO_TEST, ctermid) {
1796 ASSERT_STREQ("/dev/tty", ctermid(nullptr));
1797
1798 char buf[L_ctermid] = {};
1799 ASSERT_EQ(buf, ctermid(buf));
1800 ASSERT_STREQ("/dev/tty", buf);
1801}
Elliott Hughesd1f25a72016-08-05 15:53:03 -07001802
1803TEST(STDIO_TEST, remove) {
1804 struct stat sb;
1805
1806 TemporaryFile tf;
1807 ASSERT_EQ(0, remove(tf.filename));
1808 ASSERT_EQ(-1, lstat(tf.filename, &sb));
1809 ASSERT_EQ(ENOENT, errno);
1810
1811 TemporaryDir td;
1812 ASSERT_EQ(0, remove(td.dirname));
1813 ASSERT_EQ(-1, lstat(td.dirname, &sb));
1814 ASSERT_EQ(ENOENT, errno);
1815
1816 errno = 0;
1817 ASSERT_EQ(-1, remove(tf.filename));
1818 ASSERT_EQ(ENOENT, errno);
1819
1820 errno = 0;
1821 ASSERT_EQ(-1, remove(td.dirname));
1822 ASSERT_EQ(ENOENT, errno);
1823}
Elliott Hughesfb3873d2016-08-10 11:07:54 -07001824
1825TEST(STDIO_DEATHTEST, snprintf_30445072_known_buffer_size) {
1826 char buf[16];
1827 ASSERT_EXIT(snprintf(buf, atol("-1"), "hello"),
1828 testing::KilledBySignal(SIGABRT),
1829#if defined(NOFORTIFY)
1830 "FORTIFY: vsnprintf: size .* > SSIZE_MAX"
1831#else
1832 "FORTIFY: vsnprintf: prevented .*-byte write into 16-byte buffer"
1833#endif
1834 );
1835}
1836
1837TEST(STDIO_DEATHTEST, snprintf_30445072_unknown_buffer_size) {
1838 std::string buf = "world";
1839 ASSERT_EXIT(snprintf(&buf[0], atol("-1"), "hello"),
1840 testing::KilledBySignal(SIGABRT),
1841 "FORTIFY: vsnprintf: size .* > SSIZE_MAX");
1842}
1843
1844TEST(STDIO_TEST, sprintf_30445072) {
1845 std::string buf = "world";
1846 sprintf(&buf[0], "hello");
1847 ASSERT_EQ(buf, "hello");
1848}