Proposed 64-bit changes

Robert Elz kre at munnari.OZ.AU
Wed Apr 27 09:23:06 UTC 2005


    Date:        Tue, 26 Apr 2005 12:07:29 -0700
    From:        Paul Eggert <eggert at CS.UCLA.EDU>
    Message-ID:  <87pswhxspa.fsf at penguin.cs.ucla.edu>

  | Yes, that would be nice.  Thanks.

Patch appended.   (Patch is to localtime.c in tzcode2005h)

  | The current POSIX spec for TZ is here (look at the end of the page):

Thanks.   Bradley White sent me the text in private mail, which was
fortunate, as shortly after that I lest net connectivity for a while.

  | POSIX is a bit more restrictive than the simple spec you gave,

Not really - it just says that lots of things are undefined.   That's
fine, what we do with undefined data is up to us - including when we
treat it rationally...

  | but it'd be fine to implement it the simple way, as an extension to POSIX.

That's what I did.   That was by analogy with the current (non quoted
form) parsing, where posix says 3 or more alphabetic chars, and tzcode
allows 3 or more "anything but + - , and digits").   The new quoted code
allows 3 or more "anything but >" which is definitely more than
"alphanumeric plus '+' and '-'".   (All forms disallow \0 of course).

However, I'm not real sure that we shouldn't be a little more cautious
with this.   Do we really want to allow \n in a zone name abbreviation?
Might not that cause "unanticipated" problems for some applications
(I doubt many bother to sanitise the value of TZ before allowing it to
be used).

There may be a few other characters that should perhaps be considered
"bad" here, without going all the way to alphabetic (current locale
alphabetic) or alphanumeric (and + & -) (current locale).

I'll leave that for someone else to thing about - and perhaps also to
ponder whether there are any programs that could be convinced to do
"bad things" by putting "weird stuff" in the zone name abbreviation.

kre


-------------- next part --------------
--- localtime.c.orig	2005-04-04 22:24:32.000000000 +0700
+++ localtime.c	2005-04-27 16:07:05.000000000 +0700
@@ -124,6 +124,7 @@
 
 static long		detzcode P((const char * codep));
 static const char *	getzname P((const char * strp));
+static const char *	getqzname P((const char * strp, const char delim));
 static const char *	getnum P((const char * strp, int * nump, int min,
 				int max));
 static const char *	getsecs P((const char * strp, long * secsp));
@@ -470,6 +471,27 @@
 }
 
 /*
+** Given a pointer into an extended time zone string, scan until the ending
+** delimiter of the zone name is located.   Return a pointer to the delimiter.
+**
+** As with getzname above, the legal character set is actually quite
+** restricted, with other characters producing undefined results.
+** We choose not to care - allowing almost anything to be in the zone abbrev.
+*/
+
+static const char *
+getqzname(strp, delim)
+register const char *	strp;
+const char		delim;
+{
+	register char	c;
+
+	while ((c = *strp) != '\0' && c != delim)
+		++strp;
+	return strp;
+}
+
+/*
 ** Given a pointer into a time zone string, extract a number from that string.
 ** Check that the number is within a specified range; if it is not, return
 ** NULL.
@@ -753,8 +775,18 @@
 			stdlen = (sizeof sp->chars) - 1;
 		stdoffset = 0;
 	} else {
-		name = getzname(name);
-		stdlen = name - stdname;
+		if (*name == '<') {
+			name++;
+			stdname = name;
+			name = getqzname(name, '>');
+			if (*name != '>')
+				return (-1);
+			stdlen = name - stdname;
+			name++;
+		} else {
+			name = getzname(name);
+			stdlen = name - stdname;
+		}
 		if (stdlen < 3)
 			return -1;
 		if (*name == '\0')
@@ -767,9 +799,18 @@
 	if (load_result != 0)
 		sp->leapcnt = 0;		/* so, we're off a little */
 	if (*name != '\0') {
-		dstname = name;
-		name = getzname(name);
-		dstlen = name - dstname;	/* length of DST zone name */
+		if (*name == '<') {
+			dstname = ++name;
+			name = getqzname(name, '>');
+			if (*name != '>')
+				return -1;
+			dstlen = name - dstname;
+			name++;
+		} else {
+			dstname = name;
+			name = getzname(name);
+			dstlen = name - dstname; /* length of DST zone name */
+		}
 		if (dstlen < 3)
 			return -1;
 		if (*name != '\0' && *name != ',' && *name != ';') {


More information about the tz mailing list