This is the mail archive of the glibc-bugs@sourceware.org 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]

[Bug libc/1460] New: asctime_r and ctime_r may write beyond end of user-supplied buffer


Although ctime and asctime provide a buffer large enough for any
date string, ctime_r and asctime_r are documented to work with
a buffer of at least 26 bytes, while with large inputs, they may
write up to 33 (or more, if int is wider than 32 bits) bytes into that
user-provided buffer.

While letting ctime and asctime return a pointer to a string (including
NUL) that is longer than 26 bytes is not bad in isolation, applications
may rely on the documentation's implication that the result always
fits in a 26-byte buffer, and thus copy it without checking the length.

If you continue to support year numbers of 5 or more digits,
you should consider avoiding the overflow that currently
causes them to format year numbers like `-2147483648'.
See the example below.

As a point of reference, Solaris 10's functions return
NULL if the resulting year would be 10000 or greater.

------------------------------------------------
/* This demonstrates two problems with ctime, asctime, ctime_r and asctime_r
   when time_t is a 64-bit type:
   - integer overflow when tm_year is within 1900 of INT_MAX
   - user-space buffer overflow when tm_year is 9100 (10000-1900) or larger,
     if the caller provides a 26-byte buffer to ctime_r or asctime_r.  */

/* Show that with 64-bit time_t, glibc's ctime_r and asctime_r can write
   more than the implied maximum of 26 bytes into the user-supplied buffer.
   With the current (CVS) implementation they can write up to 33 bytes.  */
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int
main ()
{
  time_t t = 67767976233529200;
  time_t i;
  for (i = 0; i < 2; i++)
    {
      time_t k = t - i;
      char buf[100];
      char *p = ctime_r (&k, buf);
      printf ("t=%lu\n", k);
      if (p)
        fputs (p, stdout);
    }
  exit (0);
}

Here's the result of running that code on an 64-bit system:

  $ gcc -O -Wall -W ctime.c && ./a.out
  t=67767976233529200
  Wed Jan  1 00:00:00 -2147483648
  t=67767976233529199
  Tue Dec 31 23:59:59 2147483647

-- 
           Summary: asctime_r and ctime_r may write beyond end of user-
                    supplied buffer
           Product: glibc
           Version: 2.3.5
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: gotom at debian dot or dot jp
        ReportedBy: list+redhat-bugzilla at meyering dot net
                CC: glibc-bugs at sources dot redhat dot com


http://sourceware.org/bugzilla/show_bug.cgi?id=1460

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


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