Fix tzdata loading.

Android uses one large file of tzdata, so the "read up to the maximum
possible length of a valid tzfile" code in upstream localtime.c is
broken: there is always data after the current tzfile (even the
last tzfile is followed by the zone.tab data). This patch passes the
exact length through to the read(2) call so we don't over-read, rather
than have to rewrite upstream code that measures back from the "end" of
the tzfile.

The old code failed the existing time.strftime_null_tm_zone test after
updating to tzdata2016g.

Bug: http://b/31848040
Test: time.strftime_null_tm_zone
Change-Id: Iee059b5a8c051bd4952cfd80f02b00d83e489d5e
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index adc2f1b..6e88819 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -369,7 +369,7 @@
   } u;
 };
 
-static int __bionic_open_tzdata(const char*);
+static int __bionic_open_tzdata(const char*, int32_t*);
 
 /* Load tz data from the file named NAME into *SP.  Read extended
    format if DOEXTEND.  Use *LSP for temporary storage.  Return 0 on
@@ -398,7 +398,8 @@
 	}
 
 #if defined(__BIONIC__)
-	fid = __bionic_open_tzdata(name);
+	int32_t entry_length;
+	fid = __bionic_open_tzdata(name, &entry_length);
 #else
 	if (name[0] == ':')
 		++name;
@@ -424,7 +425,11 @@
 	if (fid < 0)
 	  return errno;
 
+#if defined(__BIONIC__)
+	nread = read(fid, up->buf, entry_length);
+#else
 	nread = read(fid, up->buf, sizeof up->buf);
+#endif
 	if (nread < tzheadsize) {
 	  int err = nread < 0 ? errno : EINVAL;
 	  close(fid);
@@ -2342,7 +2347,8 @@
 #include <arpa/inet.h> // For ntohl(3).
 
 static int __bionic_open_tzdata_path(const char* path_prefix_variable, const char* path_suffix,
-                                     const char* olson_id) {
+                                     const char* olson_id,
+                                     int32_t* entry_length) {
   const char* path_prefix = getenv(path_prefix_variable);
   if (path_prefix == NULL) {
     fprintf(stderr, "%s: %s not set!\n", __FUNCTION__, path_prefix_variable);
@@ -2440,6 +2446,7 @@
 
     if (strcmp(this_id, olson_id) == 0) {
       specific_zone_offset = ntohl(entry->start) + ntohl(header.data_offset);
+      *entry_length = ntohl(entry->length);
       break;
     }
 
@@ -2467,10 +2474,12 @@
   return fd;
 }
 
-static int __bionic_open_tzdata(const char* olson_id) {
-  int fd = __bionic_open_tzdata_path("ANDROID_DATA", "/misc/zoneinfo/current/tzdata", olson_id);
+static int __bionic_open_tzdata(const char* olson_id, int32_t* entry_length) {
+  int fd = __bionic_open_tzdata_path("ANDROID_DATA", "/misc/zoneinfo/current/tzdata",
+                                     olson_id, entry_length);
   if (fd < 0) {
-    fd = __bionic_open_tzdata_path("ANDROID_ROOT", "/usr/share/zoneinfo/tzdata", olson_id);
+    fd = __bionic_open_tzdata_path("ANDROID_ROOT", "/usr/share/zoneinfo/tzdata",
+                                   olson_id, entry_length);
     if (fd == -2) {
       // The first thing that 'recovery' does is try to format the current time. It doesn't have
       // any tzdata available, so we must not abort here --- doing so breaks the recovery image!