diff options
Diffstat (limited to 'tz/localtime.c')
-rw-r--r-- | tz/localtime.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/tz/localtime.c b/tz/localtime.c index 6b45254..ac3790a 100644 --- a/tz/localtime.c +++ b/tz/localtime.c @@ -413,6 +413,7 @@ tzloadbody(char const *name, struct state *sp, bool doextend, doaccess = name[0] == '/'; #endif if (!doaccess) { + char const *dot; size_t namelen = strlen(name); if (sizeof lsp->fullname - sizeof tzdirslash <= namelen) return ENAMETOOLONG; @@ -423,9 +424,16 @@ tzloadbody(char const *name, struct state *sp, bool doextend, memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash); strcpy(lsp->fullname + sizeof tzdirslash, name); - /* Set doaccess if '.' (as in "../") shows up in name. */ - if (strchr(name, '.')) - doaccess = true; + /* Set doaccess if NAME contains a ".." file name + component, as such a name could read a file outside + the TZDIR virtual subtree. */ + for (dot = name; (dot = strchr(dot, '.')); dot++) + if ((dot == name || dot[-1] == '/') && dot[1] == '.' + && (dot[2] == '/' || !dot[2])) { + doaccess = true; + break; + } + name = lsp->fullname; } if (doaccess && access(name, R_OK) != 0) @@ -781,7 +789,7 @@ static const int year_lengths[2] = { ** Return a pointer to that character. */ -static const char * +static ATTRIBUTE_PURE const char * getzname(register const char *strp) { register char c; @@ -802,7 +810,7 @@ getzname(register const char *strp) ** We don't do any checking here; checking is done later in common-case code. */ -static const char * +static ATTRIBUTE_PURE const char * getqzname(register const char *strp, const int delim) { register int c; |