• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
20 #include <fcntl.h>
21 #include <limits.h>
22 #include <math.h>
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <wchar.h>
28 #include <locale.h>
29 
30 #include <vector>
31 
32 #include "TemporaryFile.h"
33 
34 #if defined(NOFORTIFY)
35 #define STDIO_TEST stdio_nofortify
36 #else
37 #define STDIO_TEST stdio
38 #endif
39 
TEST(STDIO_TEST,flockfile_18208568_stderr)40 TEST(STDIO_TEST, flockfile_18208568_stderr) {
41   // Check that we have a _recursive_ mutex for flockfile.
42   flockfile(stderr);
43   feof(stderr); // We don't care about the result, but this needs to take the lock.
44   funlockfile(stderr);
45 }
46 
TEST(STDIO_TEST,flockfile_18208568_regular)47 TEST(STDIO_TEST, flockfile_18208568_regular) {
48   // We never had a bug for streams other than stdin/stdout/stderr, but test anyway.
49   FILE* fp = fopen("/dev/null", "w");
50   ASSERT_TRUE(fp != NULL);
51   flockfile(fp);
52   feof(fp);
53   funlockfile(fp);
54   fclose(fp);
55 }
56 
TEST(STDIO_TEST,tmpfile_fileno_fprintf_rewind_fgets)57 TEST(STDIO_TEST, tmpfile_fileno_fprintf_rewind_fgets) {
58   FILE* fp = tmpfile();
59   ASSERT_TRUE(fp != NULL);
60 
61   int fd = fileno(fp);
62   ASSERT_NE(fd, -1);
63 
64   struct stat sb;
65   int rc = fstat(fd, &sb);
66   ASSERT_NE(rc, -1);
67   ASSERT_EQ(sb.st_mode & 0777, 0600U);
68 
69   rc = fprintf(fp, "hello\n");
70   ASSERT_EQ(rc, 6);
71 
72   rewind(fp);
73 
74   char buf[16];
75   char* s = fgets(buf, sizeof(buf), fp);
76   ASSERT_TRUE(s != NULL);
77   ASSERT_STREQ("hello\n", s);
78 
79   fclose(fp);
80 }
81 
TEST(STDIO_TEST,tmpfile64)82 TEST(STDIO_TEST, tmpfile64) {
83   FILE* fp = tmpfile64();
84   ASSERT_TRUE(fp != nullptr);
85   fclose(fp);
86 }
87 
TEST(STDIO_TEST,dprintf)88 TEST(STDIO_TEST, dprintf) {
89   TemporaryFile tf;
90 
91   int rc = dprintf(tf.fd, "hello\n");
92   ASSERT_EQ(rc, 6);
93 
94   lseek(tf.fd, 0, SEEK_SET);
95   FILE* tfile = fdopen(tf.fd, "r");
96   ASSERT_TRUE(tfile != NULL);
97 
98   char buf[7];
99   ASSERT_EQ(buf, fgets(buf, sizeof(buf), tfile));
100   ASSERT_STREQ("hello\n", buf);
101   // Make sure there isn't anything else in the file.
102   ASSERT_EQ(NULL, fgets(buf, sizeof(buf), tfile));
103   fclose(tfile);
104 }
105 
TEST(STDIO_TEST,getdelim)106 TEST(STDIO_TEST, getdelim) {
107   FILE* fp = tmpfile();
108   ASSERT_TRUE(fp != NULL);
109 
110   const char* line_written = "This  is a test";
111   int rc = fprintf(fp, "%s", line_written);
112   ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
113 
114   rewind(fp);
115 
116   char* word_read = NULL;
117   size_t allocated_length = 0;
118 
119   const char* expected[] = { "This ", " ", "is ", "a ", "test" };
120   for (size_t i = 0; i < 5; ++i) {
121     ASSERT_FALSE(feof(fp));
122     ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), static_cast<int>(strlen(expected[i])));
123     ASSERT_GE(allocated_length, strlen(expected[i]));
124     ASSERT_STREQ(expected[i], word_read);
125   }
126   // The last read should have set the end-of-file indicator for the stream.
127   ASSERT_TRUE(feof(fp));
128   clearerr(fp);
129 
130   // getdelim returns -1 but doesn't set errno if we're already at EOF.
131   // It should set the end-of-file indicator for the stream, though.
132   errno = 0;
133   ASSERT_EQ(getdelim(&word_read, &allocated_length, ' ', fp), -1);
134   ASSERT_EQ(0, errno);
135   ASSERT_TRUE(feof(fp));
136 
137   free(word_read);
138   fclose(fp);
139 }
140 
TEST(STDIO_TEST,getdelim_invalid)141 TEST(STDIO_TEST, getdelim_invalid) {
142   FILE* fp = tmpfile();
143   ASSERT_TRUE(fp != NULL);
144 
145   char* buffer = NULL;
146   size_t buffer_length = 0;
147 
148   // The first argument can't be NULL.
149   errno = 0;
150   ASSERT_EQ(getdelim(NULL, &buffer_length, ' ', fp), -1);
151   ASSERT_EQ(EINVAL, errno);
152 
153   // The second argument can't be NULL.
154   errno = 0;
155   ASSERT_EQ(getdelim(&buffer, NULL, ' ', fp), -1);
156   ASSERT_EQ(EINVAL, errno);
157 
158   // The underlying fd can't be closed.
159   ASSERT_EQ(0, close(fileno(fp)));
160   errno = 0;
161   ASSERT_EQ(getdelim(&buffer, &buffer_length, ' ', fp), -1);
162   ASSERT_EQ(EBADF, errno);
163   fclose(fp);
164 }
165 
TEST(STDIO_TEST,getdelim_directory)166 TEST(STDIO_TEST, getdelim_directory) {
167   FILE* fp = fopen("/proc", "r");
168   ASSERT_TRUE(fp != NULL);
169   char* word_read;
170   size_t allocated_length;
171   ASSERT_EQ(-1, getdelim(&word_read, &allocated_length, ' ', fp));
172   fclose(fp);
173 }
174 
TEST(STDIO_TEST,getline)175 TEST(STDIO_TEST, getline) {
176   FILE* fp = tmpfile();
177   ASSERT_TRUE(fp != NULL);
178 
179   const char* line_written = "This is a test for getline\n";
180   const size_t line_count = 5;
181 
182   for (size_t i = 0; i < line_count; ++i) {
183     int rc = fprintf(fp, "%s", line_written);
184     ASSERT_EQ(rc, static_cast<int>(strlen(line_written)));
185   }
186 
187   rewind(fp);
188 
189   char* line_read = NULL;
190   size_t allocated_length = 0;
191 
192   size_t read_line_count = 0;
193   ssize_t read_char_count;
194   while ((read_char_count = getline(&line_read, &allocated_length, fp)) != -1) {
195     ASSERT_EQ(read_char_count, static_cast<int>(strlen(line_written)));
196     ASSERT_GE(allocated_length, strlen(line_written));
197     ASSERT_STREQ(line_written, line_read);
198     ++read_line_count;
199   }
200   ASSERT_EQ(read_line_count, line_count);
201 
202   // The last read should have set the end-of-file indicator for the stream.
203   ASSERT_TRUE(feof(fp));
204   clearerr(fp);
205 
206   // getline returns -1 but doesn't set errno if we're already at EOF.
207   // It should set the end-of-file indicator for the stream, though.
208   errno = 0;
209   ASSERT_EQ(getline(&line_read, &allocated_length, fp), -1);
210   ASSERT_EQ(0, errno);
211   ASSERT_TRUE(feof(fp));
212 
213   free(line_read);
214   fclose(fp);
215 }
216 
TEST(STDIO_TEST,getline_invalid)217 TEST(STDIO_TEST, getline_invalid) {
218   FILE* fp = tmpfile();
219   ASSERT_TRUE(fp != NULL);
220 
221   char* buffer = NULL;
222   size_t buffer_length = 0;
223 
224   // The first argument can't be NULL.
225   errno = 0;
226   ASSERT_EQ(getline(NULL, &buffer_length, fp), -1);
227   ASSERT_EQ(EINVAL, errno);
228 
229   // The second argument can't be NULL.
230   errno = 0;
231   ASSERT_EQ(getline(&buffer, NULL, fp), -1);
232   ASSERT_EQ(EINVAL, errno);
233 
234   // The underlying fd can't be closed.
235   ASSERT_EQ(0, close(fileno(fp)));
236   errno = 0;
237   ASSERT_EQ(getline(&buffer, &buffer_length, fp), -1);
238   ASSERT_EQ(EBADF, errno);
239   fclose(fp);
240 }
241 
TEST(STDIO_TEST,printf_ssize_t)242 TEST(STDIO_TEST, printf_ssize_t) {
243   // http://b/8253769
244   ASSERT_EQ(sizeof(ssize_t), sizeof(long int));
245   ASSERT_EQ(sizeof(ssize_t), sizeof(size_t));
246   // For our 32-bit ABI, we had a ssize_t definition that confuses GCC into saying:
247   // error: format '%zd' expects argument of type 'signed size_t',
248   //     but argument 4 has type 'ssize_t {aka long int}' [-Werror=format]
249   ssize_t v = 1;
250   char buf[32];
251   snprintf(buf, sizeof(buf), "%zd", v);
252 }
253 
254 // https://code.google.com/p/android/issues/detail?id=64886
TEST(STDIO_TEST,snprintf_a)255 TEST(STDIO_TEST, snprintf_a) {
256   char buf[BUFSIZ];
257   EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235));
258   EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf);
259 }
260 
TEST(STDIO_TEST,snprintf_lc)261 TEST(STDIO_TEST, snprintf_lc) {
262   char buf[BUFSIZ];
263   wint_t wc = L'a';
264   EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc));
265   EXPECT_STREQ("<a>", buf);
266 }
267 
TEST(STDIO_TEST,snprintf_ls)268 TEST(STDIO_TEST, snprintf_ls) {
269   char buf[BUFSIZ];
270   wchar_t* ws = NULL;
271   EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws));
272   EXPECT_STREQ("<(null)>", buf);
273 
274   wchar_t chars[] = { L'h', L'i', 0 };
275   ws = chars;
276   EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws));
277   EXPECT_STREQ("<hi>", buf);
278 }
279 
TEST(STDIO_TEST,snprintf_n)280 TEST(STDIO_TEST, snprintf_n) {
281 #if defined(__BIONIC__)
282   // http://b/14492135
283   char buf[32];
284   int i = 1234;
285   EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
286   EXPECT_EQ(1234, i);
287   EXPECT_STREQ("a n b", buf);
288 #else
289   GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
290 #endif
291 }
292 
TEST(STDIO_TEST,snprintf_smoke)293 TEST(STDIO_TEST, snprintf_smoke) {
294   char buf[BUFSIZ];
295 
296   snprintf(buf, sizeof(buf), "a");
297   EXPECT_STREQ("a", buf);
298 
299   snprintf(buf, sizeof(buf), "%%");
300   EXPECT_STREQ("%", buf);
301 
302   snprintf(buf, sizeof(buf), "01234");
303   EXPECT_STREQ("01234", buf);
304 
305   snprintf(buf, sizeof(buf), "a%sb", "01234");
306   EXPECT_STREQ("a01234b", buf);
307 
308   char* s = NULL;
309   snprintf(buf, sizeof(buf), "a%sb", s);
310   EXPECT_STREQ("a(null)b", buf);
311 
312   snprintf(buf, sizeof(buf), "aa%scc", "bb");
313   EXPECT_STREQ("aabbcc", buf);
314 
315   snprintf(buf, sizeof(buf), "a%cc", 'b');
316   EXPECT_STREQ("abc", buf);
317 
318   snprintf(buf, sizeof(buf), "a%db", 1234);
319   EXPECT_STREQ("a1234b", buf);
320 
321   snprintf(buf, sizeof(buf), "a%db", -8123);
322   EXPECT_STREQ("a-8123b", buf);
323 
324   snprintf(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010));
325   EXPECT_STREQ("a16b", buf);
326 
327   snprintf(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
328   EXPECT_STREQ("a16b", buf);
329 
330   snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
331   EXPECT_STREQ("a68719476736b", buf);
332 
333   snprintf(buf, sizeof(buf), "a%ldb", 70000L);
334   EXPECT_STREQ("a70000b", buf);
335 
336   snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
337   EXPECT_STREQ("a0xb0001234b", buf);
338 
339   snprintf(buf, sizeof(buf), "a%xz", 0x12ab);
340   EXPECT_STREQ("a12abz", buf);
341 
342   snprintf(buf, sizeof(buf), "a%Xz", 0x12ab);
343   EXPECT_STREQ("a12ABz", buf);
344 
345   snprintf(buf, sizeof(buf), "a%08xz", 0x123456);
346   EXPECT_STREQ("a00123456z", buf);
347 
348   snprintf(buf, sizeof(buf), "a%5dz", 1234);
349   EXPECT_STREQ("a 1234z", buf);
350 
351   snprintf(buf, sizeof(buf), "a%05dz", 1234);
352   EXPECT_STREQ("a01234z", buf);
353 
354   snprintf(buf, sizeof(buf), "a%8dz", 1234);
355   EXPECT_STREQ("a    1234z", buf);
356 
357   snprintf(buf, sizeof(buf), "a%-8dz", 1234);
358   EXPECT_STREQ("a1234    z", buf);
359 
360   snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef");
361   EXPECT_STREQ("Aabcdef     Z", buf);
362 
363   snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
364   EXPECT_STREQ("Ahello:1234Z", buf);
365 
366   snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
367   EXPECT_STREQ("a005:5:05z", buf);
368 
369   void* p = NULL;
370   snprintf(buf, sizeof(buf), "a%d,%pz", 5, p);
371 #if defined(__BIONIC__)
372   EXPECT_STREQ("a5,0x0z", buf);
373 #else // __BIONIC__
374   EXPECT_STREQ("a5,(nil)z", buf);
375 #endif // __BIONIC__
376 
377   snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
378   EXPECT_STREQ("a68719476736,6,7,8z", buf);
379 
380   snprintf(buf, sizeof(buf), "a_%f_b", 1.23f);
381   EXPECT_STREQ("a_1.230000_b", buf);
382 
383   snprintf(buf, sizeof(buf), "a_%g_b", 3.14);
384   EXPECT_STREQ("a_3.14_b", buf);
385 
386   snprintf(buf, sizeof(buf), "%1$s %1$s", "print_me_twice");
387   EXPECT_STREQ("print_me_twice print_me_twice", buf);
388 }
389 
390 template <typename T>
CheckInfNan(int snprintf_fn (T *,size_t,const T *,...),const T * fmt,const T * fmt_plus,const T * minus_inf,const T * inf_,const T * plus_inf,const T * minus_nan,const T * nan_,const T * plus_nan)391 void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...),
392                  const T* fmt, const T* fmt_plus,
393                  const T* minus_inf, const T* inf_, const T* plus_inf,
394                  const T* minus_nan, const T* nan_, const T* plus_nan) {
395   T buf[BUFSIZ];
396 
397   snprintf_fn(buf, sizeof(buf), fmt, nan(""));
398   EXPECT_STREQ(nan_, buf) << fmt;
399   snprintf_fn(buf, sizeof(buf), fmt, -nan(""));
400   EXPECT_STREQ(minus_nan, buf) << fmt;
401   snprintf_fn(buf, sizeof(buf), fmt_plus, nan(""));
402   EXPECT_STREQ(plus_nan, buf) << fmt_plus;
403   snprintf_fn(buf, sizeof(buf), fmt_plus, -nan(""));
404   EXPECT_STREQ(minus_nan, buf) << fmt_plus;
405 
406   snprintf_fn(buf, sizeof(buf), fmt, HUGE_VAL);
407   EXPECT_STREQ(inf_, buf) << fmt;
408   snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VAL);
409   EXPECT_STREQ(minus_inf, buf) << fmt;
410   snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VAL);
411   EXPECT_STREQ(plus_inf, buf) << fmt_plus;
412   snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VAL);
413   EXPECT_STREQ(minus_inf, buf) << fmt_plus;
414 }
415 
TEST(STDIO_TEST,snprintf_inf_nan)416 TEST(STDIO_TEST, snprintf_inf_nan) {
417   CheckInfNan(snprintf, "%a", "%+a", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
418   CheckInfNan(snprintf, "%A", "%+A", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
419   CheckInfNan(snprintf, "%e", "%+e", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
420   CheckInfNan(snprintf, "%E", "%+E", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
421   CheckInfNan(snprintf, "%f", "%+f", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
422   CheckInfNan(snprintf, "%F", "%+F", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
423   CheckInfNan(snprintf, "%g", "%+g", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
424   CheckInfNan(snprintf, "%G", "%+G", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
425 }
426 
TEST(STDIO_TEST,wsprintf_inf_nan)427 TEST(STDIO_TEST, wsprintf_inf_nan) {
428   CheckInfNan(swprintf, L"%a", L"%+a", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
429   CheckInfNan(swprintf, L"%A", L"%+A", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
430   CheckInfNan(swprintf, L"%e", L"%+e", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
431   CheckInfNan(swprintf, L"%E", L"%+E", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
432   CheckInfNan(swprintf, L"%f", L"%+f", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
433   CheckInfNan(swprintf, L"%F", L"%+F", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
434   CheckInfNan(swprintf, L"%g", L"%+g", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
435   CheckInfNan(swprintf, L"%G", L"%+G", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
436 }
437 
TEST(STDIO_TEST,snprintf_d_INT_MAX)438 TEST(STDIO_TEST, snprintf_d_INT_MAX) {
439   char buf[BUFSIZ];
440   snprintf(buf, sizeof(buf), "%d", INT_MAX);
441   EXPECT_STREQ("2147483647", buf);
442 }
443 
TEST(STDIO_TEST,snprintf_d_INT_MIN)444 TEST(STDIO_TEST, snprintf_d_INT_MIN) {
445   char buf[BUFSIZ];
446   snprintf(buf, sizeof(buf), "%d", INT_MIN);
447   EXPECT_STREQ("-2147483648", buf);
448 }
449 
TEST(STDIO_TEST,snprintf_ld_LONG_MAX)450 TEST(STDIO_TEST, snprintf_ld_LONG_MAX) {
451   char buf[BUFSIZ];
452   snprintf(buf, sizeof(buf), "%ld", LONG_MAX);
453 #if __LP64__
454   EXPECT_STREQ("9223372036854775807", buf);
455 #else
456   EXPECT_STREQ("2147483647", buf);
457 #endif
458 }
459 
TEST(STDIO_TEST,snprintf_ld_LONG_MIN)460 TEST(STDIO_TEST, snprintf_ld_LONG_MIN) {
461   char buf[BUFSIZ];
462   snprintf(buf, sizeof(buf), "%ld", LONG_MIN);
463 #if __LP64__
464   EXPECT_STREQ("-9223372036854775808", buf);
465 #else
466   EXPECT_STREQ("-2147483648", buf);
467 #endif
468 }
469 
TEST(STDIO_TEST,snprintf_lld_LLONG_MAX)470 TEST(STDIO_TEST, snprintf_lld_LLONG_MAX) {
471   char buf[BUFSIZ];
472   snprintf(buf, sizeof(buf), "%lld", LLONG_MAX);
473   EXPECT_STREQ("9223372036854775807", buf);
474 }
475 
TEST(STDIO_TEST,snprintf_lld_LLONG_MIN)476 TEST(STDIO_TEST, snprintf_lld_LLONG_MIN) {
477   char buf[BUFSIZ];
478   snprintf(buf, sizeof(buf), "%lld", LLONG_MIN);
479   EXPECT_STREQ("-9223372036854775808", buf);
480 }
481 
TEST(STDIO_TEST,snprintf_e)482 TEST(STDIO_TEST, snprintf_e) {
483   char buf[BUFSIZ];
484 
485   snprintf(buf, sizeof(buf), "%e", 1.5);
486   EXPECT_STREQ("1.500000e+00", buf);
487 
488   snprintf(buf, sizeof(buf), "%Le", 1.5l);
489   EXPECT_STREQ("1.500000e+00", buf);
490 }
491 
TEST(STDIO_TEST,snprintf_negative_zero_5084292)492 TEST(STDIO_TEST, snprintf_negative_zero_5084292) {
493   char buf[BUFSIZ];
494 
495   snprintf(buf, sizeof(buf), "%e", -0.0);
496   EXPECT_STREQ("-0.000000e+00", buf);
497   snprintf(buf, sizeof(buf), "%E", -0.0);
498   EXPECT_STREQ("-0.000000E+00", buf);
499   snprintf(buf, sizeof(buf), "%f", -0.0);
500   EXPECT_STREQ("-0.000000", buf);
501   snprintf(buf, sizeof(buf), "%F", -0.0);
502   EXPECT_STREQ("-0.000000", buf);
503   snprintf(buf, sizeof(buf), "%g", -0.0);
504   EXPECT_STREQ("-0", buf);
505   snprintf(buf, sizeof(buf), "%G", -0.0);
506   EXPECT_STREQ("-0", buf);
507   snprintf(buf, sizeof(buf), "%a", -0.0);
508   EXPECT_STREQ("-0x0p+0", buf);
509   snprintf(buf, sizeof(buf), "%A", -0.0);
510   EXPECT_STREQ("-0X0P+0", buf);
511 }
512 
TEST(STDIO_TEST,snprintf_utf8_15439554)513 TEST(STDIO_TEST, snprintf_utf8_15439554) {
514   locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0);
515   locale_t old_locale = uselocale(cloc);
516 
517   // http://b/15439554
518   char buf[BUFSIZ];
519 
520   // 1-byte character.
521   snprintf(buf, sizeof(buf), "%dx%d", 1, 2);
522   EXPECT_STREQ("1x2", buf);
523   // 2-byte character.
524   snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2);
525   EXPECT_STREQ("1¢2", buf);
526   // 3-byte character.
527   snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2);
528   EXPECT_STREQ("1€2", buf);
529   // 4-byte character.
530   snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2);
531   EXPECT_STREQ("1��2", buf);
532 
533   uselocale(old_locale);
534   freelocale(cloc);
535 }
536 
snprintf_small_stack_fn(void *)537 static void* snprintf_small_stack_fn(void*) {
538   // Make life (realistically) hard for ourselves by allocating our own buffer for the result.
539   char buf[PATH_MAX];
540   snprintf(buf, sizeof(buf), "/proc/%d", getpid());
541   return nullptr;
542 }
543 
TEST(STDIO_TEST,snprintf_small_stack)544 TEST(STDIO_TEST, snprintf_small_stack) {
545   // Is it safe to call snprintf on a thread with a small stack?
546   // (The snprintf implementation puts some pretty large buffers on the stack.)
547   pthread_attr_t a;
548   ASSERT_EQ(0, pthread_attr_init(&a));
549   ASSERT_EQ(0, pthread_attr_setstacksize(&a, PTHREAD_STACK_MIN));
550 
551   pthread_t t;
552   ASSERT_EQ(0, pthread_create(&t, &a, snprintf_small_stack_fn, nullptr));
553   ASSERT_EQ(0, pthread_join(t, nullptr));
554 }
555 
TEST(STDIO_TEST,snprintf_asterisk_overflow)556 TEST(STDIO_TEST, snprintf_asterisk_overflow) {
557   char buf[128];
558   ASSERT_EQ(5, snprintf(buf, sizeof(buf), "%.*s%c", 4, "hello world", '!'));
559   ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX/2, "hello world", '!'));
560   ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX-1, "hello world", '!'));
561   ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", INT_MAX, "hello world", '!'));
562   ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.*s%c", -1, "hello world", '!'));
563 
564   // INT_MAX-1, INT_MAX, INT_MAX+1.
565   ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483646s%c", "hello world", '!'));
566   ASSERT_EQ(12, snprintf(buf, sizeof(buf), "%.2147483647s%c", "hello world", '!'));
567   ASSERT_EQ(-1, snprintf(buf, sizeof(buf), "%.2147483648s%c", "hello world", '!'));
568   ASSERT_EQ(ENOMEM, errno);
569 }
570 
TEST(STDIO_TEST,fprintf_failures_7229520)571 TEST(STDIO_TEST, fprintf_failures_7229520) {
572   // http://b/7229520
573   FILE* fp;
574 
575   // Unbuffered case where the fprintf(3) itself fails.
576   ASSERT_NE(nullptr, fp = tmpfile());
577   setbuf(fp, NULL);
578   ASSERT_EQ(4, fprintf(fp, "epic"));
579   ASSERT_EQ(0, close(fileno(fp)));
580   ASSERT_EQ(-1, fprintf(fp, "fail"));
581   ASSERT_EQ(-1, fclose(fp));
582 
583   // Buffered case where we won't notice until the fclose(3).
584   // It's likely this is what was actually seen in http://b/7229520,
585   // and that expecting fprintf to fail is setting yourself up for
586   // disappointment. Remember to check fclose(3)'s return value, kids!
587   ASSERT_NE(nullptr, fp = tmpfile());
588   ASSERT_EQ(4, fprintf(fp, "epic"));
589   ASSERT_EQ(0, close(fileno(fp)));
590   ASSERT_EQ(4, fprintf(fp, "fail"));
591   ASSERT_EQ(-1, fclose(fp));
592 }
593 
TEST(STDIO_TEST,popen)594 TEST(STDIO_TEST, popen) {
595   FILE* fp = popen("cat /proc/version", "r");
596   ASSERT_TRUE(fp != NULL);
597 
598   char buf[16];
599   char* s = fgets(buf, sizeof(buf), fp);
600   buf[13] = '\0';
601   ASSERT_STREQ("Linux version", s);
602 
603   ASSERT_EQ(0, pclose(fp));
604 }
605 
TEST(STDIO_TEST,getc)606 TEST(STDIO_TEST, getc) {
607   FILE* fp = fopen("/proc/version", "r");
608   ASSERT_TRUE(fp != NULL);
609   ASSERT_EQ('L', getc(fp));
610   ASSERT_EQ('i', getc(fp));
611   ASSERT_EQ('n', getc(fp));
612   ASSERT_EQ('u', getc(fp));
613   ASSERT_EQ('x', getc(fp));
614   fclose(fp);
615 }
616 
TEST(STDIO_TEST,putc)617 TEST(STDIO_TEST, putc) {
618   FILE* fp = fopen("/proc/version", "r");
619   ASSERT_TRUE(fp != NULL);
620   ASSERT_EQ(EOF, putc('x', fp));
621   fclose(fp);
622 }
623 
TEST(STDIO_TEST,sscanf)624 TEST(STDIO_TEST, sscanf) {
625   char s1[123];
626   int i1;
627   double d1;
628   char s2[123];
629   ASSERT_EQ(3, sscanf("  hello 123 1.23 ", "%s %i %lf %s", s1, &i1, &d1, s2));
630   ASSERT_STREQ("hello", s1);
631   ASSERT_EQ(123, i1);
632   ASSERT_DOUBLE_EQ(1.23, d1);
633 }
634 
TEST(STDIO_TEST,cantwrite_EBADF)635 TEST(STDIO_TEST, cantwrite_EBADF) {
636   // If we open a file read-only...
637   FILE* fp = fopen("/proc/version", "r");
638 
639   // ...all attempts to write to that file should return failure.
640 
641   // They should also set errno to EBADF. This isn't POSIX, but it's traditional.
642   // glibc gets the wide-character functions wrong.
643 
644   errno = 0;
645   EXPECT_EQ(EOF, putc('x', fp));
646   EXPECT_EQ(EBADF, errno);
647 
648   errno = 0;
649   EXPECT_EQ(EOF, fprintf(fp, "hello"));
650   EXPECT_EQ(EBADF, errno);
651 
652   errno = 0;
653   EXPECT_EQ(EOF, fwprintf(fp, L"hello"));
654 #if defined(__BIONIC__)
655   EXPECT_EQ(EBADF, errno);
656 #endif
657 
658   errno = 0;
659   EXPECT_EQ(0U, fwrite("hello", 1, 2, fp));
660   EXPECT_EQ(EBADF, errno);
661 
662   errno = 0;
663   EXPECT_EQ(EOF, fputs("hello", fp));
664   EXPECT_EQ(EBADF, errno);
665 
666   errno = 0;
667   EXPECT_EQ(WEOF, fputwc(L'x', fp));
668 #if defined(__BIONIC__)
669   EXPECT_EQ(EBADF, errno);
670 #endif
671 }
672 
673 // Tests that we can only have a consistent and correct fpos_t when using
674 // f*pos functions (i.e. fpos doesn't get inside a multi byte character).
TEST(STDIO_TEST,consistent_fpos_t)675 TEST(STDIO_TEST, consistent_fpos_t) {
676   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
677   uselocale(LC_GLOBAL_LOCALE);
678 
679   FILE* fp = tmpfile();
680   ASSERT_TRUE(fp != NULL);
681 
682   wchar_t mb_one_bytes = L'h';
683   wchar_t mb_two_bytes = 0x00a2;
684   wchar_t mb_three_bytes = 0x20ac;
685   wchar_t mb_four_bytes = 0x24b62;
686 
687   // Write to file.
688   ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp)));
689   ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
690   ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
691   ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
692 
693   rewind(fp);
694 
695   // Record each character position.
696   fpos_t pos1;
697   fpos_t pos2;
698   fpos_t pos3;
699   fpos_t pos4;
700   fpos_t pos5;
701   EXPECT_EQ(0, fgetpos(fp, &pos1));
702   ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
703   EXPECT_EQ(0, fgetpos(fp, &pos2));
704   ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
705   EXPECT_EQ(0, fgetpos(fp, &pos3));
706   ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
707   EXPECT_EQ(0, fgetpos(fp, &pos4));
708   ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
709   EXPECT_EQ(0, fgetpos(fp, &pos5));
710 
711 #if defined(__BIONIC__)
712   // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD
713   // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In
714   // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE
715   // structure.
716   ASSERT_EQ(0, static_cast<off_t>(pos1));
717   ASSERT_EQ(1, static_cast<off_t>(pos2));
718   ASSERT_EQ(3, static_cast<off_t>(pos3));
719   ASSERT_EQ(6, static_cast<off_t>(pos4));
720   ASSERT_EQ(10, static_cast<off_t>(pos5));
721 #endif
722 
723   // Exercise back and forth movements of the position.
724   ASSERT_EQ(0, fsetpos(fp, &pos2));
725   ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
726   ASSERT_EQ(0, fsetpos(fp, &pos1));
727   ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
728   ASSERT_EQ(0, fsetpos(fp, &pos4));
729   ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
730   ASSERT_EQ(0, fsetpos(fp, &pos3));
731   ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
732   ASSERT_EQ(0, fsetpos(fp, &pos5));
733   ASSERT_EQ(WEOF, fgetwc(fp));
734 
735   fclose(fp);
736 }
737 
738 // Exercise the interaction between fpos and seek.
TEST(STDIO_TEST,fpos_t_and_seek)739 TEST(STDIO_TEST, fpos_t_and_seek) {
740   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
741   uselocale(LC_GLOBAL_LOCALE);
742 
743   // In glibc-2.16 fseek doesn't work properly in wide mode
744   // (https://sourceware.org/bugzilla/show_bug.cgi?id=14543). One workaround is
745   // to close and re-open the file. We do it in order to make the test pass
746   // with all glibcs.
747 
748   TemporaryFile tf;
749   FILE* fp = fdopen(tf.fd, "w+");
750   ASSERT_TRUE(fp != NULL);
751 
752   wchar_t mb_two_bytes = 0x00a2;
753   wchar_t mb_three_bytes = 0x20ac;
754   wchar_t mb_four_bytes = 0x24b62;
755 
756   // Write to file.
757   ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
758   ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
759   ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));
760 
761   fflush(fp);
762   fclose(fp);
763 
764   fp = fopen(tf.filename, "r");
765   ASSERT_TRUE(fp != NULL);
766 
767   // Store a valid position.
768   fpos_t mb_two_bytes_pos;
769   ASSERT_EQ(0, fgetpos(fp, &mb_two_bytes_pos));
770 
771   // Move inside mb_four_bytes with fseek.
772   long offset_inside_mb = 6;
773   ASSERT_EQ(0, fseek(fp, offset_inside_mb, SEEK_SET));
774 
775   // Store the "inside multi byte" position.
776   fpos_t pos_inside_mb;
777   ASSERT_EQ(0, fgetpos(fp, &pos_inside_mb));
778 #if defined(__BIONIC__)
779   ASSERT_EQ(offset_inside_mb, static_cast<off_t>(pos_inside_mb));
780 #endif
781 
782   // Reading from within a byte should produce an error.
783   ASSERT_EQ(WEOF, fgetwc(fp));
784   ASSERT_EQ(EILSEQ, errno);
785 
786   // Reverting to a valid position should work.
787   ASSERT_EQ(0, fsetpos(fp, &mb_two_bytes_pos));
788   ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
789 
790   // Moving withing a multi byte with fsetpos should work but reading should
791   // produce an error.
792   ASSERT_EQ(0, fsetpos(fp, &pos_inside_mb));
793   ASSERT_EQ(WEOF, fgetwc(fp));
794   ASSERT_EQ(EILSEQ, errno);
795 
796   fclose(fp);
797 }
798 
TEST(STDIO_TEST,fmemopen)799 TEST(STDIO_TEST, fmemopen) {
800   char buf[16];
801   memset(buf, 0, sizeof(buf));
802   FILE* fp = fmemopen(buf, sizeof(buf), "r+");
803   ASSERT_EQ('<', fputc('<', fp));
804   ASSERT_NE(EOF, fputs("abc>\n", fp));
805   fflush(fp);
806 
807   ASSERT_STREQ("<abc>\n", buf);
808 
809   rewind(fp);
810 
811   char line[16];
812   char* s = fgets(line, sizeof(line), fp);
813   ASSERT_TRUE(s != NULL);
814   ASSERT_STREQ("<abc>\n", s);
815 
816   fclose(fp);
817 }
818 
TEST(STDIO_TEST,fmemopen_NULL)819 TEST(STDIO_TEST, fmemopen_NULL) {
820   FILE* fp = fmemopen(nullptr, 128, "r+");
821   ASSERT_NE(EOF, fputs("xyz\n", fp));
822 
823   rewind(fp);
824 
825   char line[16];
826   char* s = fgets(line, sizeof(line), fp);
827   ASSERT_TRUE(s != NULL);
828   ASSERT_STREQ("xyz\n", s);
829 
830   fclose(fp);
831 }
832 
TEST(STDIO_TEST,fmemopen_EINVAL)833 TEST(STDIO_TEST, fmemopen_EINVAL) {
834   char buf[16];
835 
836   // Invalid size.
837   errno = 0;
838   ASSERT_EQ(nullptr, fmemopen(buf, 0, "r+"));
839   ASSERT_EQ(EINVAL, errno);
840 
841   // No '+' with NULL buffer.
842   errno = 0;
843   ASSERT_EQ(nullptr, fmemopen(nullptr, 0, "r"));
844   ASSERT_EQ(EINVAL, errno);
845 }
846 
TEST(STDIO_TEST,open_memstream)847 TEST(STDIO_TEST, open_memstream) {
848   char* p = nullptr;
849   size_t size = 0;
850   FILE* fp = open_memstream(&p, &size);
851   ASSERT_NE(EOF, fputs("hello, world!", fp));
852   fclose(fp);
853 
854   ASSERT_STREQ("hello, world!", p);
855   ASSERT_EQ(strlen("hello, world!"), size);
856   free(p);
857 }
858 
TEST(STDIO_TEST,open_memstream_EINVAL)859 TEST(STDIO_TEST, open_memstream_EINVAL) {
860 #if defined(__BIONIC__)
861   char* p;
862   size_t size;
863 
864   // Invalid buffer.
865   errno = 0;
866   ASSERT_EQ(nullptr, open_memstream(nullptr, &size));
867   ASSERT_EQ(EINVAL, errno);
868 
869   // Invalid size.
870   errno = 0;
871   ASSERT_EQ(nullptr, open_memstream(&p, nullptr));
872   ASSERT_EQ(EINVAL, errno);
873 #else
874   GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
875 #endif
876 }
877 
TEST(STDIO_TEST,fdopen_CLOEXEC)878 TEST(STDIO_TEST, fdopen_CLOEXEC) {
879   int fd = open("/proc/version", O_RDONLY);
880   ASSERT_TRUE(fd != -1);
881 
882   // This fd doesn't have O_CLOEXEC...
883   int flags = fcntl(fd, F_GETFD);
884   ASSERT_TRUE(flags != -1);
885   ASSERT_EQ(0, flags & FD_CLOEXEC);
886 
887   FILE* fp = fdopen(fd, "re");
888   ASSERT_TRUE(fp != NULL);
889 
890   // ...but the new one does.
891   flags = fcntl(fileno(fp), F_GETFD);
892   ASSERT_TRUE(flags != -1);
893   ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
894 
895   fclose(fp);
896   close(fd);
897 }
898 
TEST(STDIO_TEST,freopen_CLOEXEC)899 TEST(STDIO_TEST, freopen_CLOEXEC) {
900   FILE* fp = fopen("/proc/version", "r");
901   ASSERT_TRUE(fp != NULL);
902 
903   // This FILE* doesn't have O_CLOEXEC...
904   int flags = fcntl(fileno(fp), F_GETFD);
905   ASSERT_TRUE(flags != -1);
906   ASSERT_EQ(0, flags & FD_CLOEXEC);
907 
908   fp = freopen("/proc/version", "re", fp);
909 
910   // ...but the new one does.
911   flags = fcntl(fileno(fp), F_GETFD);
912   ASSERT_TRUE(flags != -1);
913   ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
914 
915   fclose(fp);
916 }
917 
TEST(STDIO_TEST,fopen64_freopen64)918 TEST(STDIO_TEST, fopen64_freopen64) {
919   FILE* fp = fopen64("/proc/version", "r");
920   ASSERT_TRUE(fp != nullptr);
921   fp = freopen64("/proc/version", "re", fp);
922   ASSERT_TRUE(fp != nullptr);
923   fclose(fp);
924 }
925 
926 // https://code.google.com/p/android/issues/detail?id=81155
927 // http://b/18556607
TEST(STDIO_TEST,fread_unbuffered_pathological_performance)928 TEST(STDIO_TEST, fread_unbuffered_pathological_performance) {
929   FILE* fp = fopen("/dev/zero", "r");
930   ASSERT_TRUE(fp != NULL);
931 
932   // Make this stream unbuffered.
933   setvbuf(fp, 0, _IONBF, 0);
934 
935   char buf[65*1024];
936   memset(buf, 0xff, sizeof(buf));
937 
938   time_t t0 = time(NULL);
939   for (size_t i = 0; i < 1024; ++i) {
940     ASSERT_EQ(1U, fread(buf, 64*1024, 1, fp));
941   }
942   time_t t1 = time(NULL);
943 
944   fclose(fp);
945 
946   // 1024 64KiB reads should have been very quick.
947   ASSERT_LE(t1 - t0, 1);
948 
949   for (size_t i = 0; i < 64*1024; ++i) {
950     ASSERT_EQ('\0', buf[i]);
951   }
952   for (size_t i = 64*1024; i < 65*1024; ++i) {
953     ASSERT_EQ('\xff', buf[i]);
954   }
955 }
956 
TEST(STDIO_TEST,fread_EOF)957 TEST(STDIO_TEST, fread_EOF) {
958   std::string digits("0123456789");
959   FILE* fp = fmemopen(&digits[0], digits.size(), "r");
960 
961   // Try to read too much, but little enough that it still fits in the FILE's internal buffer.
962   char buf1[4 * 4];
963   memset(buf1, 0, sizeof(buf1));
964   ASSERT_EQ(2U, fread(buf1, 4, 4, fp));
965   ASSERT_STREQ("0123456789", buf1);
966   ASSERT_TRUE(feof(fp));
967 
968   rewind(fp);
969 
970   // Try to read way too much so stdio tries to read more direct from the stream.
971   char buf2[4 * 4096];
972   memset(buf2, 0, sizeof(buf2));
973   ASSERT_EQ(2U, fread(buf2, 4, 4096, fp));
974   ASSERT_STREQ("0123456789", buf2);
975   ASSERT_TRUE(feof(fp));
976 
977   fclose(fp);
978 }
979 
test_fread_from_write_only_stream(size_t n)980 static void test_fread_from_write_only_stream(size_t n) {
981   FILE* fp = fopen("/dev/null", "w");
982   std::vector<char> buf(n, 0);
983   errno = 0;
984   ASSERT_EQ(0U, fread(&buf[0], n, 1, fp));
985   ASSERT_EQ(EBADF, errno);
986   ASSERT_TRUE(ferror(fp));
987   ASSERT_FALSE(feof(fp));
988   fclose(fp);
989 }
990 
TEST(STDIO_TEST,fread_from_write_only_stream_slow_path)991 TEST(STDIO_TEST, fread_from_write_only_stream_slow_path) {
992   test_fread_from_write_only_stream(1);
993 }
994 
TEST(STDIO_TEST,fread_from_write_only_stream_fast_path)995 TEST(STDIO_TEST, fread_from_write_only_stream_fast_path) {
996   test_fread_from_write_only_stream(64*1024);
997 }
998 
test_fwrite_after_fread(size_t n)999 static void test_fwrite_after_fread(size_t n) {
1000   TemporaryFile tf;
1001 
1002   FILE* fp = fdopen(tf.fd, "w+");
1003   ASSERT_EQ(1U, fwrite("1", 1, 1, fp));
1004   fflush(fp);
1005 
1006   // We've flushed but not rewound, so there's nothing to read.
1007   std::vector<char> buf(n, 0);
1008   ASSERT_EQ(0U, fread(&buf[0], 1, buf.size(), fp));
1009   ASSERT_TRUE(feof(fp));
1010 
1011   // But hitting EOF doesn't prevent us from writing...
1012   errno = 0;
1013   ASSERT_EQ(1U, fwrite("2", 1, 1, fp)) << strerror(errno);
1014 
1015   // And if we rewind, everything's there.
1016   rewind(fp);
1017   ASSERT_EQ(2U, fread(&buf[0], 1, buf.size(), fp));
1018   ASSERT_EQ('1', buf[0]);
1019   ASSERT_EQ('2', buf[1]);
1020 
1021   fclose(fp);
1022 }
1023 
TEST(STDIO_TEST,fwrite_after_fread_slow_path)1024 TEST(STDIO_TEST, fwrite_after_fread_slow_path) {
1025   test_fwrite_after_fread(16);
1026 }
1027 
TEST(STDIO_TEST,fwrite_after_fread_fast_path)1028 TEST(STDIO_TEST, fwrite_after_fread_fast_path) {
1029   test_fwrite_after_fread(64*1024);
1030 }
1031 
1032 // http://b/19172514
TEST(STDIO_TEST,fread_after_fseek)1033 TEST(STDIO_TEST, fread_after_fseek) {
1034   TemporaryFile tf;
1035 
1036   FILE* fp = fopen(tf.filename, "w+");
1037   ASSERT_TRUE(fp != nullptr);
1038 
1039   char file_data[12288];
1040   for (size_t i = 0; i < 12288; i++) {
1041     file_data[i] = i;
1042   }
1043   ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp));
1044   fclose(fp);
1045 
1046   fp = fopen(tf.filename, "r");
1047   ASSERT_TRUE(fp != nullptr);
1048 
1049   char buffer[8192];
1050   size_t cur_location = 0;
1051   // Small read to populate internal buffer.
1052   ASSERT_EQ(100U, fread(buffer, 1, 100, fp));
1053   ASSERT_EQ(memcmp(file_data, buffer, 100), 0);
1054 
1055   cur_location = static_cast<size_t>(ftell(fp));
1056   // Large read to force reading into the user supplied buffer and bypassing
1057   // the internal buffer.
1058   ASSERT_EQ(8192U, fread(buffer, 1, 8192, fp));
1059   ASSERT_EQ(memcmp(file_data+cur_location, buffer, 8192), 0);
1060 
1061   // Small backwards seek to verify fseek does not reuse the internal buffer.
1062   ASSERT_EQ(0, fseek(fp, -22, SEEK_CUR)) << strerror(errno);
1063   cur_location = static_cast<size_t>(ftell(fp));
1064   ASSERT_EQ(22U, fread(buffer, 1, 22, fp));
1065   ASSERT_EQ(memcmp(file_data+cur_location, buffer, 22), 0);
1066 
1067   fclose(fp);
1068 }
1069 
1070 // https://code.google.com/p/android/issues/detail?id=184847
TEST(STDIO_TEST,fread_EOF_184847)1071 TEST(STDIO_TEST, fread_EOF_184847) {
1072   TemporaryFile tf;
1073   char buf[6] = {0};
1074 
1075   FILE* fw = fopen(tf.filename, "w");
1076   ASSERT_TRUE(fw != nullptr);
1077 
1078   FILE* fr = fopen(tf.filename, "r");
1079   ASSERT_TRUE(fr != nullptr);
1080 
1081   fwrite("a", 1, 1, fw);
1082   fflush(fw);
1083   ASSERT_EQ(1U, fread(buf, 1, 1, fr));
1084   ASSERT_STREQ("a", buf);
1085 
1086   // 'fr' is now at EOF.
1087   ASSERT_EQ(0U, fread(buf, 1, 1, fr));
1088   ASSERT_TRUE(feof(fr));
1089 
1090   // Write some more...
1091   fwrite("z", 1, 1, fw);
1092   fflush(fw);
1093 
1094   // ...and check that we can read it back.
1095   // (BSD thinks that once a stream has hit EOF, it must always return EOF. SysV disagrees.)
1096   ASSERT_EQ(1U, fread(buf, 1, 1, fr));
1097   ASSERT_STREQ("z", buf);
1098 
1099   // But now we're done.
1100   ASSERT_EQ(0U, fread(buf, 1, 1, fr));
1101 
1102   fclose(fr);
1103   fclose(fw);
1104 }
1105 
TEST(STDIO_TEST,fclose_invalidates_fd)1106 TEST(STDIO_TEST, fclose_invalidates_fd) {
1107   // The typical error we're trying to help people catch involves accessing
1108   // memory after it's been freed. But we know that stdin/stdout/stderr are
1109   // special and don't get deallocated, so this test uses stdin.
1110   ASSERT_EQ(0, fclose(stdin));
1111 
1112   // Even though using a FILE* after close is undefined behavior, I've closed
1113   // this bug as "WAI" too many times. We shouldn't hand out stale fds,
1114   // especially because they might actually correspond to a real stream.
1115   errno = 0;
1116   ASSERT_EQ(-1, fileno(stdin));
1117   ASSERT_EQ(EBADF, errno);
1118 }
1119 
TEST(STDIO_TEST,fseek_ftell_unseekable)1120 TEST(STDIO_TEST, fseek_ftell_unseekable) {
1121 #if defined(__BIONIC__) // glibc has fopencookie instead.
1122   auto read_fn = [](void*, char*, int) { return -1; };
1123   FILE* fp = funopen(nullptr, read_fn, nullptr, nullptr, nullptr);
1124   ASSERT_TRUE(fp != nullptr);
1125 
1126   // Check that ftell balks on an unseekable FILE*.
1127   errno = 0;
1128   ASSERT_EQ(-1, ftell(fp));
1129   ASSERT_EQ(ESPIPE, errno);
1130 
1131   // SEEK_CUR is rewritten as SEEK_SET internally...
1132   errno = 0;
1133   ASSERT_EQ(-1, fseek(fp, 0, SEEK_CUR));
1134   ASSERT_EQ(ESPIPE, errno);
1135 
1136   // ...so it's worth testing the direct seek path too.
1137   errno = 0;
1138   ASSERT_EQ(-1, fseek(fp, 0, SEEK_SET));
1139   ASSERT_EQ(ESPIPE, errno);
1140 
1141   fclose(fp);
1142 #else
1143   GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
1144 #endif
1145 }
1146 
TEST(STDIO_TEST,funopen_EINVAL)1147 TEST(STDIO_TEST, funopen_EINVAL) {
1148 #if defined(__BIONIC__)
1149   errno = 0;
1150   ASSERT_EQ(nullptr, funopen(nullptr, nullptr, nullptr, nullptr, nullptr));
1151   ASSERT_EQ(EINVAL, errno);
1152 #else
1153   GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
1154 #endif
1155 }
1156 
TEST(STDIO_TEST,funopen_seek)1157 TEST(STDIO_TEST, funopen_seek) {
1158 #if defined(__BIONIC__)
1159   auto read_fn = [](void*, char*, int) { return -1; };
1160 
1161   auto seek_fn = [](void*, fpos_t, int) -> fpos_t { return 0xfedcba12; };
1162   auto seek64_fn = [](void*, fpos64_t, int) -> fpos64_t { return 0xfedcba12345678; };
1163 
1164   FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr);
1165   ASSERT_TRUE(fp != nullptr);
1166   fpos_t pos;
1167 #if defined(__LP64__)
1168   EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno);
1169   EXPECT_EQ(0xfedcba12LL, pos);
1170 #else
1171   EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno);
1172   EXPECT_EQ(EOVERFLOW, errno);
1173 #endif
1174 
1175   FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr);
1176   ASSERT_TRUE(fp64 != nullptr);
1177   fpos64_t pos64;
1178   EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno);
1179   EXPECT_EQ(0xfedcba12345678, pos64);
1180 #else
1181   GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n";
1182 #endif
1183 }
1184 
TEST(STDIO_TEST,lots_of_concurrent_files)1185 TEST(STDIO_TEST, lots_of_concurrent_files) {
1186   std::vector<TemporaryFile*> tfs;
1187   std::vector<FILE*> fps;
1188 
1189   for (size_t i = 0; i < 256; ++i) {
1190     TemporaryFile* tf = new TemporaryFile;
1191     tfs.push_back(tf);
1192     FILE* fp = fopen(tf->filename, "w+");
1193     fps.push_back(fp);
1194     fprintf(fp, "hello %zu!\n", i);
1195     fflush(fp);
1196   }
1197 
1198   for (size_t i = 0; i < 256; ++i) {
1199     rewind(fps[i]);
1200 
1201     char buf[BUFSIZ];
1202     ASSERT_TRUE(fgets(buf, sizeof(buf), fps[i]) != nullptr);
1203 
1204     char expected[BUFSIZ];
1205     snprintf(expected, sizeof(expected), "hello %zu!\n", i);
1206     ASSERT_STREQ(expected, buf);
1207 
1208     fclose(fps[i]);
1209     delete tfs[i];
1210   }
1211 }
1212 
AssertFileOffsetAt(FILE * fp,off64_t offset)1213 static void AssertFileOffsetAt(FILE* fp, off64_t offset) {
1214   EXPECT_EQ(offset, ftell(fp));
1215   EXPECT_EQ(offset, ftello(fp));
1216   EXPECT_EQ(offset, ftello64(fp));
1217   fpos_t pos;
1218   fpos64_t pos64;
1219   EXPECT_EQ(0, fgetpos(fp, &pos));
1220   EXPECT_EQ(0, fgetpos64(fp, &pos64));
1221 #if defined(__BIONIC__)
1222   EXPECT_EQ(offset, static_cast<off64_t>(pos));
1223   EXPECT_EQ(offset, static_cast<off64_t>(pos64));
1224 #else
1225   GTEST_LOG_(INFO) << "glibc's fpos_t is opaque.\n";
1226 #endif
1227 }
1228 
TEST(STDIO_TEST,seek_tell_family_smoke)1229 TEST(STDIO_TEST, seek_tell_family_smoke) {
1230   TemporaryFile tf;
1231   FILE* fp = fdopen(tf.fd, "w+");
1232 
1233   // Initially we should be at 0.
1234   AssertFileOffsetAt(fp, 0);
1235 
1236   // Seek to offset 8192.
1237   ASSERT_EQ(0, fseek(fp, 8192, SEEK_SET));
1238   AssertFileOffsetAt(fp, 8192);
1239   fpos_t eight_k_pos;
1240   ASSERT_EQ(0, fgetpos(fp, &eight_k_pos));
1241 
1242   // Seek forward another 8192...
1243   ASSERT_EQ(0, fseek(fp, 8192, SEEK_CUR));
1244   AssertFileOffsetAt(fp, 8192 + 8192);
1245   fpos64_t sixteen_k_pos64;
1246   ASSERT_EQ(0, fgetpos64(fp, &sixteen_k_pos64));
1247 
1248   // Seek back 8192...
1249   ASSERT_EQ(0, fseek(fp, -8192, SEEK_CUR));
1250   AssertFileOffsetAt(fp, 8192);
1251 
1252   // Since we haven't written anything, the end is also at 0.
1253   ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
1254   AssertFileOffsetAt(fp, 0);
1255 
1256   // Check that our fpos64_t from 16KiB works...
1257   ASSERT_EQ(0, fsetpos64(fp, &sixteen_k_pos64));
1258   AssertFileOffsetAt(fp, 8192 + 8192);
1259   // ...as does our fpos_t from 8192.
1260   ASSERT_EQ(0, fsetpos(fp, &eight_k_pos));
1261   AssertFileOffsetAt(fp, 8192);
1262 
1263   // Do fseeko and fseeko64 work too?
1264   ASSERT_EQ(0, fseeko(fp, 1234, SEEK_SET));
1265   AssertFileOffsetAt(fp, 1234);
1266   ASSERT_EQ(0, fseeko64(fp, 5678, SEEK_SET));
1267   AssertFileOffsetAt(fp, 5678);
1268 
1269   fclose(fp);
1270 }
1271 
TEST(STDIO_TEST,fseek_fseeko_EINVAL)1272 TEST(STDIO_TEST, fseek_fseeko_EINVAL) {
1273   TemporaryFile tf;
1274   FILE* fp = fdopen(tf.fd, "w+");
1275 
1276   // Bad whence.
1277   errno = 0;
1278   ASSERT_EQ(-1, fseek(fp, 0, 123));
1279   ASSERT_EQ(EINVAL, errno);
1280   errno = 0;
1281   ASSERT_EQ(-1, fseeko(fp, 0, 123));
1282   ASSERT_EQ(EINVAL, errno);
1283   errno = 0;
1284   ASSERT_EQ(-1, fseeko64(fp, 0, 123));
1285   ASSERT_EQ(EINVAL, errno);
1286 
1287   // Bad offset.
1288   errno = 0;
1289   ASSERT_EQ(-1, fseek(fp, -1, SEEK_SET));
1290   ASSERT_EQ(EINVAL, errno);
1291   errno = 0;
1292   ASSERT_EQ(-1, fseeko(fp, -1, SEEK_SET));
1293   ASSERT_EQ(EINVAL, errno);
1294   errno = 0;
1295   ASSERT_EQ(-1, fseeko64(fp, -1, SEEK_SET));
1296   ASSERT_EQ(EINVAL, errno);
1297 
1298   fclose(fp);
1299 }
1300