This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: mktime.c fixes (part 2 of 6): don't reject pre-1969 timestamps


Ulrich Drepper <drepper@redhat.com> writes:

> The interfaces in the libc are more widely and uncontrolled used.
> Nobody must use them for anything and to ensure this the interface
> must be restrictive.

Sorry, I don't follow what you're saying.  Surely you're not arguing
that glibc must not offer any extensions to POSIX?  (If that were
true, glibc would have to require that 'long int' must be only 32 bits
wide, since anything wider is a POSIX extension.  :-)

Anyway, there are two issues here:

  (1) negative time_t values, and
  (2) whether times are normalized before or after any overflow checking.

You're talking about (1), but I was talking about (2) which you
haven't addressed yet.  The C Standard and POSIX both say that that
struct tm components can be outside their normal ranges, so long as
the date and time are OK after normalization.

For example, if my time zone is UTC and I ask glibc mktime to convert
the equivalent of 2039-01-(-346) 00:00:00 to time_t, it works
correctly and generates 2038-01-19 00:00:00; see the test program at
the end of this message.  It's true that the year 2039 is out of
time_t range (assuming 32-bit signed time_t), and that the day -346 is
out of range for January 2039, but both facts are irrelevant; mktime
is supposed to normalize the tm components first, not reject them
simply because one or two happen to be out of range.  This principle
also holds for 1968-12-(397) 00:00:00: that time stamp is in range
after normalization, so mktime must convert it to 0.

> This is why 1969 is recognized.  Epoch is 00:00:00 1970-01-01 UTC, so
> only 1969-12-31 needs to be handled.  Not 1968.

This is incorrect for the reasons cited above.

Also, if Roland's suggestion of 23 December is adopted (see
<http://sources.redhat.com/ml/libc-alpha/2003-12/msg00171.html>),
this will be incorrect for a different reason, as UTC offsets might be
more than 365 days.


Here's that test program I mentioned.

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

struct tm tm;

int
main (void)
{
  time_t t;
  if (putenv ("TZ=UTC0") != 0)
    abort ();
  tm.tm_year = 2039 - 1900;
  tm.tm_mon = 1 - 1;
  tm.tm_mday = -346;
  tm.tm_hour = 0;
  tm.tm_min = 0;
  tm.tm_sec = 0;
  t = mktime (&tm);
  printf ("time = %lu %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n",
	  (unsigned long int) t,
	  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
	  tm.tm_min, tm.tm_sec);
  return 0;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]