|
Hi,
I just found a bug in an embedded port of lua which didn't support
sprintf(). Specifically, the work-around:
#define sprintf(s,fmt,...) snprintf(s, sizeof(s), fmt, __VA_ARGS__)
is broken. Consider correct code such as:
char *b = ...; sprintf(b, "%d", 1);
found in lstrlib.c.
This, however, begs the question: should lua switch to snprintf()?
First, I don't think anyone will dispute that snprintf() is more
robust than sprintf(). Rather, the problem is with portability.
While snprintf() was formalized in c99, and almost all the C compilers
have been supporting it since forever, there's been one holdout -
Microsoft - they have had a somewhat recalcitrant attitude towards C
standards compliance and, consequently, snprintf wasn't an option
(Microsoft does have sprintf_s() and _snprintf() but they have
different semantics).
http://en.cppreference.com/w/c/io/fprintf
https://msdn.microsoft.com/en-us/library/2ts7cx93%28v=vs.120%29.aspx
However, recently we've been seeing something of a shift in
Microsoft's attitude. Specifically Visual Studio 14/15 should support
things like snprintf:
http://blogs.msdn.com/b/vcblog/archive/2014/06/03/visual-studio-14-ctp.aspx
So I'd like to float the idea of adopting snprintf(), for instance:
- just assume snprintf (which would require a very recent Microsoft C compiler)
- define Lsnprintf() as snprintf() and use that, except on old windows
systems which can wrap _snprintf() and deal with the different
semantics
- define Lsnrintf() as snprintf() and use that, except on windows
where it is re-defined as sprintf() (ignore the length parameter);
this means things are no worse than what we have now
Andrew