mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 19:50:24 +02:00
* stime.c (scm_strftime): Recognize a return value of zero from
strftime as buffer overflow and take care to detect a valid zero length result regardless. Thanks to David Barts!
This commit is contained in:
parent
23d919087e
commit
a15e6dcc8f
1 changed files with 21 additions and 3 deletions
|
@ -62,6 +62,10 @@
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
# ifdef TIME_WITH_SYS_TIME
|
# ifdef TIME_WITH_SYS_TIME
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
|
@ -560,7 +564,7 @@ SCM_DEFINE (scm_strftime, "strftime", 2, 0, 0,
|
||||||
|
|
||||||
char *tbuf;
|
char *tbuf;
|
||||||
int size = 50;
|
int size = 50;
|
||||||
char *fmt;
|
char *fmt, *myfmt;
|
||||||
int len;
|
int len;
|
||||||
SCM result;
|
SCM result;
|
||||||
|
|
||||||
|
@ -571,6 +575,16 @@ SCM_DEFINE (scm_strftime, "strftime", 2, 0, 0,
|
||||||
fmt = SCM_ROCHARS (format);
|
fmt = SCM_ROCHARS (format);
|
||||||
len = SCM_ROLENGTH (format);
|
len = SCM_ROLENGTH (format);
|
||||||
|
|
||||||
|
/* Ugly hack: strftime can return 0 if its buffer is too small,
|
||||||
|
but some valid time strings (e.g. "%p") can sometimes produce
|
||||||
|
a zero-byte output string! Workaround is to prepend a junk
|
||||||
|
character to the format string, so that valid returns are always
|
||||||
|
nonzero. */
|
||||||
|
myfmt = SCM_MUST_MALLOC (len+2);
|
||||||
|
*myfmt = 'x';
|
||||||
|
strncpy(myfmt+1, fmt, len);
|
||||||
|
myfmt[len+1] = 0;
|
||||||
|
|
||||||
tbuf = SCM_MUST_MALLOC (size);
|
tbuf = SCM_MUST_MALLOC (size);
|
||||||
{
|
{
|
||||||
#if !defined (HAVE_TM_ZONE)
|
#if !defined (HAVE_TM_ZONE)
|
||||||
|
@ -603,7 +617,10 @@ SCM_DEFINE (scm_strftime, "strftime", 2, 0, 0,
|
||||||
tzset ();
|
tzset ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while ((len = strftime (tbuf, size, fmt, &t)) == size)
|
/* POSIX says strftime returns 0 on buffer overrun, but old
|
||||||
|
systems (i.e. libc 4 on GNU/Linux) might return `size' in that
|
||||||
|
case. */
|
||||||
|
while ((len = strftime (tbuf, size, myfmt, &t)) == 0 || len == size)
|
||||||
{
|
{
|
||||||
scm_must_free (tbuf);
|
scm_must_free (tbuf);
|
||||||
size *= 2;
|
size *= 2;
|
||||||
|
@ -619,8 +636,9 @@ SCM_DEFINE (scm_strftime, "strftime", 2, 0, 0,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
result = scm_makfromstr (tbuf, len, 0);
|
result = scm_makfromstr (tbuf+1, len-1, 0);
|
||||||
scm_must_free (tbuf);
|
scm_must_free (tbuf);
|
||||||
|
scm_must_free(myfmt);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue