summaryrefslogtreecommitdiff
path: root/tz/localtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'tz/localtime.c')
-rw-r--r--tz/localtime.c18
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;