Q: Can the current asctime_r() implementation potentially be threat unsafe?

Jeff Johnston jjohnstn@redhat.com
Wed Mar 3 22:19:00 GMT 2004

Christian Baribeau wrote:
> Allo!
> I may have found a potential bug in the reentrant implementation of the
> asctime_r(). Here is the implementation taken from newlib CVS.
> char *
> _DEFUN (asctime_r, (tim_p, result),
> _CONST struct tm *tim_p _AND
> char *result)
> {
> static _CONST char day_name[7][3] = {
> "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
> };
> static _CONST char mon_name[12][3] = {
> "Jan", "Feb", "Mar", "Apr", "May", "Jun",
> "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
> };
> sprintf (result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", <- Potential Problem
> day_name[tim_p->tm_wday],
> mon_name[tim_p->tm_mon],
> tim_p->tm_mday, tim_p->tm_hour, tim_p->tm_min,
> tim_p->tm_sec, 1900 + tim_p->tm_year);
> return result;
> }
> Can someone confirm that the call to sprintf() should be replaced with
> _sprintf_r() with the appropriate struct _reent in order to make asctime_r()
> reentrant or that the current implementation can be considered "thread
> safe".
> Thank you,
> Christian

It is fine Christian.  With sprintf, the file struct passed to _vfprintf_r is on 
the stack so any file locking is irrelevant.  The only reentrancy call made in 
_vfprintf_r will be to _mbtowc_r and it is called with a state field that is a 
local variable.  Even though the errno field to reference will not be the 
thread's errno field, the format string is single-byte so errno will not be 
modified by this call.  There are no other reentrancy struct items that can be 
modified (e.g. no other ways to cause errno to be set) so the call is fine.

Note that asctime_r is not a newlib invention like other _r functions.  It does 
not take a reentrancy struct argument.

-- Jeff J.

More information about the Newlib mailing list