Bug 1460 - asctime_r and ctime_r may write beyond end of user-supplied buffer
Summary: asctime_r and ctime_r may write beyond end of user-supplied buffer
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.3.5
: P2 normal
Target Milestone: ---
Assignee: GOTO Masanori
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-11 10:01 UTC by Jim Meyering
Modified: 2016-05-20 19:51 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security+


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jim Meyering 2005-10-11 10:01:56 UTC
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
Comment 1 Ulrich Drepper 2005-10-14 15:17:23 UTC
The current code now uses snprintf to prevent buffer overflows.