COMMAND

    The Windows "April Fools 2001" bug

SYSTEMS AFFECTED

    Win9x, NT

PROBLEM

    Richard M. Smith found following.  He has discovered a serious bug
    in Windows which will cause many Windows applications to give  the
    incorrect time starting on April  1, 2001.  Although this  new bug
    is not technically a Y2K bug, it is similar because programs  will
    fail on  a particular  day in  the next  century.   The bug causes
    Windows applications to give times which are off by one hour  even
    though the  Windows clock  shows the  correct time.   The bug will
    continue for one week until  April 8th of 2001, when  applications
    will again show  the correct time.   The bug occurs  under Windows
    95, 98, and NT.

    A bit  of background.   In the  United State  and Canada, daylight
    saving time (DST) always starts  on the first Sunday in  April and
    ends on the last Sunday in  October.  More information of the  DST
    rules can be found in the article at

        http://www.energy.ca.gov/daylightsaving.html

    The problem  is caused  by the  Visual C++  runtime library  being
    confused  and  assuming  that  daylight  saving time doesn't start
    until April  the 8th.   In fact,  daylight saving  time starts  on
    April 1 in the year 2001.   The confusion appears to be caused  by
    the fact that  April 1 falls  on a Sunday  in the year  2001.  The
    same bug  occurs in  other years  where April  1 also  falls on  a
    Sunday.  The last time this happened was in 1990 and after 2001 it
    will occur again in  2007.  If April  1 falls on any  other day of
    the week, the bug does not occur.

    Richard created a live demo page on the Web that tests for the bug
    in  Netscape  Navigator  4  and  Internet  Explorer  4  which both
    apparently use Visual C++ runtime  library.  The URL of  this demo
    page is:

        http://security.pharlap.com/y2k/demo1.htm

    Richard believes  that the  bug was  introduced in  version 4.1 of
    Visual C++.  It is present in versions 4.2, 5.0, and 6.0 according
    to his testing.   He has written a  small program in C  that tests
    for the problem.  The source  code for the test program is  below.
    This  "April  Fools  2001"  bug  is  present  in  the  localtime()
    function, but is probably also in other functions defined in the C
    language "time.h" header file.

    //
    // APRIL1.C -- Simple test program for the "April's Fools 2001" bug
    //
    // by Richard M. Smith (rms@pharlap.com)
    // copyright (C) 1999
    //

    #include <stdio.h>
    #include <time.h>
    #include <string.h>

    #define SECS_PER_HOUR (60 * 60)
    #define SECS_PER_DAY (24 * SECS_PER_HOUR)
    #define SECS_PER_YEAR (365 * SECS_PER_DAY)

    #define START (3 * SECS_PER_DAY)
    #define INCR (23 * SECS_PER_HOUR)
    #define MAXTIMES ((0x80000000L - START) / INCR)

    void print_time(time_t mytime);

    char *month_tab[] =
    {
            "January",
            "February",
            "March",
            "April",
            "May",
            "June",
            "July",
            "August",
            "September",
            "October",
            "November",
            "December"
    };

    char *dow_tab[] =
    {
            "Sunday",
            "Monday",
            "Tuesday",
            "Wednesday",
            "Thursday",
            "Friday",
            "Saturday"
    };

    int main()

    {

            print_time(0x3AC796D0);  // Sunday, April 1, 2001
            print_time(0x3ACF2B70);  // Saturday, April 7, 2001
            print_time(0x3AD06EE0);  // Sunday, April 8, 2001
            return 0;

    }

    //
    // print_time -- print out a time_t value converted by localtime()
    //

    void print_time(time_t mytime)

    {

        char month[100];
        char dow[100];
        struct tm *tmp;

        tmp = localtime(&mytime);
        if(tmp == NULL)
        {
            printf("0x%08lX = Invalid time\n", mytime);
            return;
        }
        if(tmp->tm_mon >= 0 && tmp->tm_mon <= 11)
            strcpy(month, month_tab[tmp->tm_mon]);
        else
            sprintf(month, "BadMonth=%d", tmp->tm_mon);
        if(tmp->tm_wday >= 0 && tmp->tm_wday <= 6)
            strcpy(dow, dow_tab[tmp->tm_wday]);
        else
            sprintf(month, "BadDOW=%d", tmp->tm_wday);
        printf("0x%08lX = %s, %s %d, %d -- %d:%02d:%02d %s -- DOY=%d\n",
               mytime, dow, month, tmp->tm_mday, tmp->tm_year + 1900,
               tmp->tm_hour, tmp->tm_min, tmp->tm_sec, _tzname[tmp->tm_isdst != 0],
               tmp->tm_yday);
        return;

    }

SOLUTION

    Microsoft is mentioning fixes  available for the April  Fools 2001
    bug in msvcrt.dll

        http://msdn.microsoft.com/visualc/headlines/2001.asp

    MS includes 2 utilities in  the NT Resource Kit, both  designed to
    (at  least  in  part)   address  Daylight  Savings  Time   issues:
    TZEdit.exe and Timezone.exe.

    TZEdit.exe allows you to edit all Time Zones, and even create new
    ones.  Timezone.exe  allows you to  specify exact dates  for start
    and end of DST.  This utility would be useful if your DST was  not
    based on, e.g., 1st Sunday of  April, but instead based on 5th  of
    April every year.  Timezone.exe makes its changes directly in  the
    registry. Using Timezone.exe means you  will have to run it  every
    year! Since it records  the start and end  dates for DST as  exact
    dates, as  opposed to  relative dates,  you'd have  to change them
    over and  over again.   TZEdit does  a better  job, but  it  can't
    overcome the problems described by Richard Smith.