On Fri, Sep 12, 2008 at 9:07 PM, Nelson H. F. Beebe <[EMAIL PROTECTED]> wrote:
> Yesterday, I installed findutils-4.5.2 on about 25 flavors of Unix
> in our labs. Today, we found that it gets a segment violation
> on Sun Solaris SPARC, easily replicated like this:
Thanks for your bug report!
> find ~/.cshrc -printf '%TY'
>
> The backtrace of the core dump shows
>
> #0 0xff209678 in doformat () from /lib/libc.so.1
> #1 0xff209710 in strftime () from /lib/libc.so.1
> #2 0x0001734c in format_date (ts={tv_sec = 1221016463, tv_nsec = 381255880},
> kind=89) at pred.c:2097
[...]
Thanks. I suspect that this occurs because Solaris unconditionally
writes a terminating null character into the buffer, even if the
passed in size parameter is zero.
POSIX requires:
"If the total number of resulting bytes including the terminating null
byte is not more than maxsize, strftime() shall return the number of
bytes placed into the array pointed to by s, not including the
terminating null byte. Otherwise, 0 shall be returned and the contents
of the array are unspecified."
(See http://www.opengroup.org/onlinepubs/009695399/functions/strftime.html)
The code we have right now assumes that 0 will be correctly returned
if the buffer is too small. However, it appears to me after some
digging around that Solaris may return a nonzero count even if the
buffer is too small. So I would like you to try the attached patch
if you don't mind, to work around the problem.
> The installation tests did not catch this error: all of them passed.
Yes, the installation tests are particularly weak on time-related
tests and output.
> This may not logically be the desired thing (e.g., a 1KB size is
> arbitrary), but it allows the simple test to complete correctly, and
> prevents a NULL pointer being passed to strftime().
I believe I understand why this does work around the problem. I'm
not set against using your patch. However, please try the attached
patch instead.
Thanks,
James.
Index: find/pred.c
===================================================================
RCS file: /sources/findutils/findutils/find/pred.c,v
retrieving revision 1.116
diff -u -p -r1.116 pred.c
--- find/pred.c 21 Jun 2008 12:19:30 -0000 1.116
+++ find/pred.c 13 Sep 2008 12:55:13 -0000
@@ -2068,7 +2068,7 @@ static char*
do_time_format (const char *fmt, const struct tm *p, const char *ns, size_t ns_size)
{
static char *buf = NULL;
- static size_t buf_size = 0u;
+ static size_t buf_size;
char *timefmt = NULL;
boolean done = false;
struct tm altered_time;
@@ -2092,10 +2092,21 @@ do_time_format (const char *fmt, const s
else
altered_time.tm_sec += 11;
+ /* If we call strftime() with buf_size=0, the program will coredump
+ * on Solaris, since it unconditionally writes the terminating null
+ * character.
+ */
+ buf_size = 1u;
+ buf = xmalloc (buf_size);
while (!done)
{
- const size_t buf_used = strftime (buf, buf_size, timefmt, p);
- if (0 != buf_used)
+ /* I'm not sure that Solaris will return 0 when the buffer is too small.
+ * Therefore we do not check for (buf_used != 0) as the termination
+ * condition.
+ */
+ size_t buf_used = strftime (buf, buf_size, timefmt, p);
+ if (buf_used /* Conforming POSIX system */
+ && (buf_used < buf_size)) /* Solaris workaround */
{
char *altbuf;
size_t i, n;