Merge "[MIPS] Fix bionic test build"
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 0861015..cf0fd6b 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -2174,6 +2174,10 @@
 time_t
 mktime(struct tm *tmp)
 {
+#if __ANDROID__
+  int saved_errno = errno;
+#endif
+
   time_t t;
   int err = lock();
   if (err) {
@@ -2183,6 +2187,10 @@
   tzset_unlocked();
   t = mktime_tzname(lclptr, tmp, true);
   unlock();
+
+#if __ANDROID__
+  errno = (t == -1) ? EOVERFLOW : saved_errno;
+#endif
   return t;
 }
 
diff --git a/tests/Android.mk b/tests/Android.mk
index f59b439..482c828 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -32,6 +32,9 @@
 bionic_tests_module := libtest_invalid-zero_shstrndx.so
 include $(LOCAL_PATH)/Android.build.prebuilt.mk
 
+bionic_tests_module := libtest_invalid-empty_shdr_table.so
+include $(LOCAL_PATH)/Android.build.prebuilt.mk
+
 ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
 build_host := true
 else
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 549cebb..9f1b401 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1186,4 +1186,12 @@
   ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
 }
 
+TEST(dlfcn, dlopen_invalid_empty_shdr_table) {
+  std::string libpath = std::string(getenv("ANDROID_DATA")) + PREBUILT_ELF_PATH + "/libtest_invalid-empty_shdr_table.so";
+  void* handle = dlopen(libpath.c_str(), RTLD_NOW);
+  ASSERT_TRUE(handle == nullptr);
+  std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has no section headers";
+  ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
+}
+
 #endif
diff --git a/tests/prebuilt-elf-files/arm/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/arm/libtest_invalid-empty_shdr_table.so
new file mode 100755
index 0000000..ebeaa19
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so
new file mode 100755
index 0000000..12ce90f
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/x86/libtest_invalid-empty_shdr_table.so
new file mode 100755
index 0000000..97cf006
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so
new file mode 100755
index 0000000..2052442
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 028a359..48c299a 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -102,20 +102,41 @@
 #if !defined(__LP64__)
   // 32-bit bionic stupidly had a signed 32-bit time_t.
   ASSERT_EQ(-1, mktime(&t));
+  ASSERT_EQ(EOVERFLOW, errno);
 #else
   // Everyone else should be using a signed 64-bit time_t.
   ASSERT_GE(sizeof(time_t) * 8, 64U);
 
   setenv("TZ", "America/Los_Angeles", 1);
   tzset();
+  errno = 0;
   ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
+  ASSERT_EQ(0, errno);
 
   setenv("TZ", "UTC", 1);
   tzset();
+  errno = 0;
   ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
+  ASSERT_EQ(0, errno);
 #endif
 }
 
+TEST(time, mktime_EOVERFLOW) {
+  struct tm t;
+  memset(&t, 0, sizeof(tm));
+  t.tm_year = 0;
+  t.tm_mon = 2;
+  t.tm_mday = 10;
+
+  errno = 0;
+  ASSERT_NE(static_cast<time_t>(-1), mktime(&t));
+  ASSERT_EQ(0, errno);
+
+  t.tm_year = INT_MAX;
+  ASSERT_EQ(static_cast<time_t>(-1), mktime(&t));
+  ASSERT_EQ(EOVERFLOW, errno);
+}
+
 TEST(time, strftime) {
   setenv("TZ", "UTC", 1);