Merge "Don't search off the end of the index for bad Olson ids."
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 689bbd3..8a54e81 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -2305,7 +2305,13 @@
static const size_t NAME_LENGTH = 40;
unsigned char buf[NAME_LENGTH + 3 * sizeof(int32_t)];
- while (TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf))) == (ssize_t) sizeof(buf)) {
+
+ size_t id_count = (ntohl(header.data_offset) - ntohl(header.index_offset)) / sizeof(buf);
+ for (size_t i = 0; i < id_count; ++i) {
+ if (TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf))) != (ssize_t) sizeof(buf)) {
+ break;
+ }
+
char this_id[NAME_LENGTH + 1];
memcpy(this_id, buf, NAME_LENGTH);
this_id[NAME_LENGTH] = '\0';
diff --git a/tests/Android.mk b/tests/Android.mk
index 633a6a9..46427ec 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -74,6 +74,7 @@
string_test.cpp \
strings_test.cpp \
stubs_test.cpp \
+ time_test.cpp \
unistd_test.cpp \
test_dynamic_ldflags = -Wl,--export-dynamic -Wl,-u,DlSymTestFunction
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
new file mode 100644
index 0000000..9a5a706
--- /dev/null
+++ b/tests/time_test.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/cdefs.h>
+#include <features.h>
+#include <gtest/gtest.h>
+
+#include <time.h>
+
+#ifdef __BIONIC__ // mktime_tz is a bionic extension.
+#include <libc/private/bionic_time.h>
+TEST(time, mktime_tz) {
+ struct tm epoch;
+ memset(&epoch, 0, sizeof(tm));
+ epoch.tm_year = 1970 - 1900;
+ epoch.tm_mon = 1;
+ epoch.tm_mday = 1;
+
+ // Alphabetically first. Coincidentally equivalent to UTC.
+ ASSERT_EQ(2678400, mktime_tz(&epoch, "Africa/Abidjan"));
+
+ // Alphabetically last. Coincidentally equivalent to UTC.
+ ASSERT_EQ(2678400, mktime_tz(&epoch, "Zulu"));
+
+ // Somewhere in the middle, not UTC.
+ ASSERT_EQ(2707200, mktime_tz(&epoch, "America/Los_Angeles"));
+
+ // Missing. Falls back to UTC.
+ ASSERT_EQ(2678400, mktime_tz(&epoch, "PST"));
+}
+#endif