From cjc@cc942873-a.ewndsr1.nj.home.com  Mon Jan  3 18:50:04 2000
Return-Path: <cjc@cc942873-a.ewndsr1.nj.home.com>
Received: from cc942873-a.ewndsr1.nj.home.com (cc942873-a.ewndsr1.nj.home.com [24.2.89.207])
	by hub.freebsd.org (Postfix) with ESMTP id DD69314FBA
	for <FreeBSD-gnats-submit@freebsd.org>; Mon,  3 Jan 2000 18:50:02 -0800 (PST)
	(envelope-from cjc@cc942873-a.ewndsr1.nj.home.com)
Received: (from cjc@localhost)
	by cc942873-a.ewndsr1.nj.home.com (8.9.3/8.9.3) id VAA11470;
	Mon, 3 Jan 2000 21:54:28 -0500 (EST)
	(envelope-from cjc)
Message-Id: <200001040254.VAA11470@cc942873-a.ewndsr1.nj.home.com>
Date: Mon, 3 Jan 2000 21:54:28 -0500 (EST)
From: "Crist J. Clark" <cjc@cc942873-a.ewndsr1.nj.home.com>
Reply-To: cjc@cc942873-a.ewndsr1.nj.home.com
To: FreeBSD-gnats-submit@freebsd.org
Subject: Y2k bug in at(1)
X-Send-Pr-Version: 3.2

>Number:         15872
>Category:       bin
>Synopsis:       Y2k bug in at(1)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    sheldonh
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jan  3 19:00:01 PST 2000
>Closed-Date:    Thu Jun 22 05:36:03 PDT 2000
>Last-Modified:  Thu Jun 22 05:37:04 PDT 2000
>Originator:     Crist J. Clark
>Release:        FreeBSD 3.4-STABLE i386
>Organization:
>Environment:

	Present in all FreeBSD versions checked (2.x.x and 3.x). Also
seen in other BSDs.

>Description:

	There is a Y2k bug in at(1). The following portion of code
can cause valid time specifications to return 'garbled time' errors,

/*
 * assign_date() assigns a date, wrapping to next year if needed
 */
static void
assign_date(struct tm *tm, long mday, long mon, long year)
{
    if (year > 99) {
	if (year > 1899)
	    year -= 1900;
	else
	    panic("garbled time");
    } ...

When this function is passed the current year in tm_year format, 100,
it will complain it is a garbled time. However, it is a legal value.

>How-To-Repeat:

	Try to queue an atjob in the following manner,

% at 10:30am wed
at: garbled time

However, that is a legal command line.

>Fix:
	
	The parsetime.c code, which is excerpted above, is a _very_
complex piece of work. I hesitate to write a patch to fix this small
problem since it might create greater ones. I leave it to someone with
more familiarity with the code. (However, I am not sure why the 
'year > 99' check is needed at all.)

	In the mean time, the previous command line can will work if
you phrase it,

% at 10:30 + 2 days

You may need to try other convoluted constructions to work around
other formats that might trigger the bug.

>Release-Note:
>Audit-Trail:

From: Sheldon Hearn <sheldonh@uunet.co.za>
To: cjc@cc942873-a.ewndsr1.nj.home.com
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/15872: Y2k bug in at(1) 
Date: Tue, 04 Jan 2000 12:55:34 +0200

 On Mon, 03 Jan 2000 21:54:28 EST, "Crist J. Clark" wrote:
 
 >     if (year > 99) {
 > 	if (year > 1899)
 > 	    year -= 1900;
 > 	else
 > 	    panic("garbled time");
 >     } ...
 
 What odd code. :-)
 
 I'd fix this by making proper tm_year adjustments before those calls to
 assign_date() which pass it a tm_year value.
 
 Have you chatted to the authors?  Are they unreachable?
 
 Ciao,
 Sheldon.
 
 Index: parsetime.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/at/parsetime.c,v
 retrieving revision 1.19
 diff -u -d -r1.19 parsetime.c
 --- parsetime.c	1999/12/05 19:57:14	1.19
 +++ parsetime.c	2000/01/04 10:54:54
 @@ -495,7 +495,7 @@
  
  	    tm->tm_wday = wday;
  
 -	    assign_date(tm, mday, tm->tm_mon, tm->tm_year);
 +	    assign_date(tm, mday, tm->tm_mon, 1900 + tm->tm_year);
  	    break;
  
      case NUMBER:
 @@ -527,7 +527,7 @@
  	    }
  	    else if (tlen == 6 || tlen == 8) {
  		if (tlen == 8) {
 -		    year = (mon % 10000) - 1900;
 +		    year = mon % 10000;
  		    mon /= 10000;
  		}
  		else {
 

From: "Sergey N. Voronkov" <serg@dor.zaural.ru>
To: cjc@cc942873-a.ewndsr1.nj.home.com
Cc: FreeBSD-gnats-submit@FreeBSD.ORG, sheldonh@uunet.co.za
Subject: Re: bin/15872: Y2k bug in at(1)
Date: Fri, 21 Jan 2000 10:28:10 +0500 (YEKT)

 > >     if (year > 99) {
 > >      if (year > 1899)
 > >          year -= 1900;
 > >      else
 > >          panic("garbled time");
 > >     } ...
 >  
 > What odd code. :-)
 > 
 > I'd fix this by making proper tm_year adjustments before those calls to
 > assign_date() which pass it a tm_year value.
 >     
 > Have you chatted to the authors?  Are they unreachable?
 >     
 > Ciao,
 > Sheldon.
 >     
 > Index: parsetime.c
 > ===================================================================
 > RCS file: /home/ncvs/src/usr.bin/at/parsetime.c,v
 > retrieving revision 1.19
 [...]
 
 It's another way to do this right. I'v adapted OpenBSD Team patch
 .
 And, Mr. Sheldon, can you, please, make one of two changes in STABLE branch ?
 
 Best Regards,
 Sergey N. Voronkov.
 
 --- /usr/src/usr.bin/at/parsetime.c	Sun Aug 29 21:25:26 1999
 +++ parsetime.c	Fri Jan 21 10:21:56 2000
 @@ -417,27 +417,30 @@
  static void
  assign_date(struct tm *tm, long mday, long mon, long year)
  {
 -    if (year > 99) {
 -	if (year > 1899)
 -	    year -= 1900;
 -	else
 -	    panic("garbled time");
 -    } else if (year != -1) {
 +
 +    /*
 +     * Convert year into tm_year format (year - 1900).
 +     * We may be given the year in 2 digit, 4 digit, or tm_year format.
 +     */
 +#define TM_YEAR_BASE 1900
 +    if (year != -1) {
  	struct tm *lt;
  	time_t now;
  
  	time(&now);
  	lt = localtime(&now);
  
 -	/*
 -	 * check if the specified year is in the next century.
 -	 * allow for one year of user error as many people will
 -	 * enter n - 1 at the start of year n.
 -	 */
 -	if (year < (lt->tm_year % 100) - 1)
 -	    year += 100;
 -	/* adjust for the year 2000 and beyond */
 -	year += lt->tm_year - (lt->tm_year % 100);
 +        if (year >= TM_YEAR_BASE)
 +                year -= TM_YEAR_BASE;   /* convert from 4 digit year */
 +        else if (year < 100) {
 +                /* Convert to tm_year assuming current century */
 +                year += (lt->tm_year / 100) * 100;
 +
 +                if (year == lt->tm_year - 1)
 +                       year++;         /* Common off by one error */
 +                else if (year < lt->tm_year)
 +                       year += 100;    /* must be in next century */
 +        }
      }
  
      if (year < 0 &&
 

From: "Sergey N. Voronkov" <serg@dor.zaural.ru>
To: wollman@freebsd.org
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/15872: Y2k bug in at(1)
Date: Thu, 27 Jan 2000 18:53:59 +0500 (YEKT)

 Hello Nick!
 
 As a last person deeply touched /usr/src/usr.bin/at/parsetime.c, 
 could you, please, review and apply this patch to at (PR/15872).
 Patch is based on OpenBSD code.
 
 Sorry, I test it only on my 3.4-STABLE system. In CURRENT may be
 need to make some changes in patch header. assign_date() has some bug
 in both versions.
 
 Serg N. Voronkov
 
 --- parsetime.c.orig	Mon Aug 30 00:42:00 1999
 +++ parsetime.c	Thu Jan 27 18:50:48 2000
 @@ -417,27 +417,28 @@
  static void
  assign_date(struct tm *tm, long mday, long mon, long year)
  {
 -    if (year > 99) {
 -	if (year > 1899)
 -	    year -= 1900;
 -	else
 -	    panic("garbled time");
 -    } else if (year != -1) {
 -	struct tm *lt;
 -	time_t now;
  
 -	time(&now);
 -	lt = localtime(&now);
 +   /*
 +    * Convert year into tm_year format (year - 1900).
 +    */
 +    if (year != -1) {
 +	if (year >= 1900)
 +		year -= 1900;   /* convert from 4 digit year */
 +	else if (year < 100) {
 +		/* convert from 2 digit year */
 +		struct tm *lt;
 +		time_t now;
  
 -	/*
 -	 * check if the specified year is in the next century.
 -	 * allow for one year of user error as many people will
 -	 * enter n - 1 at the start of year n.
 -	 */
 -	if (year < (lt->tm_year % 100) - 1)
 -	    year += 100;
 -	/* adjust for the year 2000 and beyond */
 -	year += lt->tm_year - (lt->tm_year % 100);
 +		time(&now);
 +		lt = localtime(&now);
 +
 +		/* Convert to tm_year assuming current century */
 +		year += (lt->tm_year / 100) * 100;
 +
 +		if (year == lt->tm_year - 1) year++;
 +		else if (year < lt->tm_year)
 +			year += 100;    /* must be in next century */
 +	}
      }
  
      if (year < 0 &&
 
Responsible-Changed-From-To: freebsd-bugs->sheldonh 
Responsible-Changed-By: sheldonh 
Responsible-Changed-When: Sat Feb 19 08:00:33 PST 2000 
Responsible-Changed-Why:  
Reminder for me to tackle this after 4.0-RELEASE if nobody else has 
done so by then. 

From: Sheldon Hearn <sheldonh@uunet.co.za>
To: "Sergey N. Voronkov" <serg@dor.zaural.ru>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/15872: Y2k bug in at(1) 
Date: Sat, 19 Feb 2000 17:59:53 +0200

 On Fri, 21 Jan 2000 10:28:10 +0500, "Sergey N. Voronkov" wrote:
 
 > It's another way to do this right. I'v adapted OpenBSD Team patch.
 > And, Mr. Sheldon, can you, please, make one of two changes in STABLE
 > branch ?
 
 Hi Sergey,
 
 I'm sorry I've taken so long to get back to you on this one.  Work
 pressure picked up unexpectedly.
 
 It looks like this one will have to wait 'til after 4.0-RELEASE.
 
 Apologies,
 Sheldon.
 
State-Changed-From-To: open->analyzed 
State-Changed-By: sheldonh 
State-Changed-When: Mon Mar 27 01:32:44 PST 2000 
State-Changed-Why:  
Committed in rev 1.20 of src/usr.bin/at/parsetime.c .  We'll give it 
some time in HEAD before merging onto RELENG_4 and RELENG_3 branches. 
Thanks! 
State-Changed-From-To: analyzed->closed 
State-Changed-By: sheldonh 
State-Changed-When: Thu Jun 22 05:36:03 PDT 2000 
State-Changed-Why:  
Merged onto RELENG_4 branch in rev 1.19.2.1 of parsetime.c and 
onto RELENG_3 branch in rev 1.16.2.2, both on Fri Apr 14 2000. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=15872 
>Unformatted:
