Allow 32-bit fseeko/fseeko64 SEEK_CUR/SEEK_SET to exceed 2 GiB

Bug: http://b/68837650
Test: /data/nativetest/bionic-unit-tests/bionic-unit-tests
Test: /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static
Test: /data/nativetest64/bionic-unit-tests/bionic-unit-tests
Change-Id: I367e0238c31d35f76d8ad89fd0aa27ecfeb7c149
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 87a0eae..05a19d1 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -2148,3 +2148,37 @@
 
   ASSERT_EQ(0, fclose(fp));
 }
+
+TEST(STDIO_TEST, fseek_64bit) {
+  TemporaryFile tf;
+  FILE* fp = fopen64(tf.filename, "w+");
+  ASSERT_TRUE(fp != nullptr);
+  ASSERT_EQ(0, fseeko64(fp, 0x2'0000'0000, SEEK_SET));
+  ASSERT_EQ(0x2'0000'0000, ftello64(fp));
+  ASSERT_EQ(0, fseeko64(fp, 0x1'0000'0000, SEEK_CUR));
+  ASSERT_EQ(0x3'0000'0000, ftello64(fp));
+  ASSERT_EQ(0, fclose(fp));
+}
+
+// POSIX requires that fseek/fseeko fail with EOVERFLOW if the new file offset
+// isn't representable in long/off_t.
+TEST(STDIO_TEST, fseek_overflow_32bit) {
+  TemporaryFile tf;
+  FILE* fp = fopen64(tf.filename, "w+");
+  ASSERT_EQ(0, ftruncate64(fileno(fp), 0x2'0000'0000));
+
+  // Bionic implements overflow checking for SEEK_CUR, but glibc doesn't.
+#if defined(__BIONIC__) && !defined(__LP64__)
+  ASSERT_EQ(0, fseek(fp, 0x7fff'ffff, SEEK_SET));
+  ASSERT_EQ(-1, fseek(fp, 1, SEEK_CUR));
+  ASSERT_EQ(EOVERFLOW, errno);
+#endif
+
+  // Neither Bionic nor glibc implement the overflow checking for SEEK_END.
+  // (Aside: FreeBSD's libc is an example of a libc that checks both SEEK_CUR
+  // and SEEK_END -- many C libraries check neither.)
+  ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
+  ASSERT_EQ(0x2'0000'0000, ftello64(fp));
+
+  fclose(fp);
+}