[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
asctime_r and ctime_r may write beyond end of user-supplied buffer
From: |
Jim Meyering |
Subject: |
asctime_r and ctime_r may write beyond end of user-supplied buffer |
Date: |
Wed, 05 Oct 2005 18:17:21 +0200 |
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 32 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 32 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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- asctime_r and ctime_r may write beyond end of user-supplied buffer,
Jim Meyering <=