Previously, the code could have had quirky behavior if a TZif
file's TZ string was corrupted. Now, the code reliably ignores
such a string.
* time/tzfile.c (__tzfile_compute): If the proleptic TZ string
is invalid, do not use it.
* time/tzset.c (__tzset_parse_tz): Return a success indication.
Do not try to parse DST rule if there is no DST.
---
time/tzfile.c | 5 +++--
time/tzset.c | 15 ++++++---------
time/tzset.h | 2 +-
3 files changed, 10 insertions(+), 12 deletions(-)
@@ -620,8 +620,9 @@ __tzfile_compute (__time64_t timer, int use_localtime,
goto found;
}
- /* Parse the proleptic TZ string. */
- __tzset_parse_tz (tzspec);
+ /* Parse the proleptic TZ string. If this fails do not use it. */
+ if (__glibc_unlikely (! __tzset_parse_tz (tzspec)))
+ goto use_last;
/* Convert to broken down structure. If this fails do not
use the string. */
@@ -350,7 +350,7 @@ parse_rule (const char **tzp, int whichrule)
}
/* Parse a proleptic TZ string. */
-void
+bool
__tzset_parse_tz (const char *tz)
{
/* Clear out old state and reset to UTC. */
@@ -360,17 +360,13 @@ __tzset_parse_tz (const char *tz)
tz_rules[0].name = tz_rules[1].name = "UTC";
/* Get the standard time zone abbreviations. */
- if (parse_tzname (&tz, 0) && parse_offset (&tz, 0))
+ bool ok = parse_tzname (&tz, 0) && parse_offset (&tz, 0);
+ if (ok)
{
/* Get the DST time zone abbreviation (if any). */
if (*tz != '\0')
- {
- if (parse_tzname (&tz, 1))
- parse_offset (&tz, 1);
- /* Figure out the standard <-> DST rules. */
- if (parse_rule (&tz, 0))
- parse_rule (&tz, 1);
- }
+ ok = (parse_tzname (&tz, 1) && parse_offset (&tz, 1)
+ && parse_rule (&tz, 0) && parse_rule (&tz, 1));
else
{
/* There is no DST. */
@@ -380,6 +376,7 @@ __tzset_parse_tz (const char *tz)
}
update_vars ();
+ return ok;
}
/* Interpret the TZ envariable. */
@@ -14,7 +14,7 @@ extern void __tzfile_read (const char *file) attribute_hidden;
extern void __tzfile_compute (__time64_t timer, int use_localtime,
int *leap_correct, bool *leap_hit,
struct tm *tp) attribute_hidden;
-extern void __tzset_parse_tz (const char *tz) attribute_hidden;
+extern bool __tzset_parse_tz (const char *tz) attribute_hidden;
extern void __tz_compute (__time64_t timer, struct tm *tm)
__THROW attribute_hidden;