Greg Ercolano wrote:
> ..and complete build output just to show how it worked (and what
> warning messages were left) over here:
>
> BUILD LOG:
>
> http://seriss.com/people/erco/fltk/tmp/okbuild-6971-win32-vsexpress-2008.txt
Just a reminder; the warnings from the WIN32 build about snprintf() being
unsafe
in the above are true; the /WINDOWS/ implementation of snprintf() is bad,
it does
not work the way the gnu snprintf() does ['correctly']. (See their docs for
why)
There is no easy solution to this, as the 'new' function Microsoft
recommends,
_snprintf_s(), does /not/ have the same calling parameters, so you can't
just
trivially change _snprintf() -> _snprintf_s().
Here's some details from an email I sent someone while testing the boundary
conditions of Microsoft's snprintf() under win32 vs linux, and was shocked
at the different results:
* * *
[..]it seems [the Microsoft] _snprintf() doesn't follow the C99 spec,
so the function apparently works incorrectly on the very
boundary conditions it's supposed to protect us from. eg:
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#define snprintf _snprintf
#define strcpy strcpy_s
#endif /*MICROSOFT*/
int main() {
int ret;
char ss[20];
strcpy(ss, "********XY"); // 'X' and 'Y' should never be touched
or seen
ret=snprintf(ss, 8, "1234%s","56"); fprintf(stderr,"[OK] RET=%d,
SS='%s' X OK? %s\n", ret, ss, ss[8]=='X'?"yes":"NO!");
ret=snprintf(ss, 8, "1234%s","567"); fprintf(stderr,"[OK] RET=%d,
SS='%s' X OK? %s\n", ret, ss, ss[8]=='X'?"yes":"NO!");
ret=snprintf(ss, 8, "1234%s","5678"); fprintf(stderr,"[BAD] RET=%d,
SS='%s' X OK? %s\n", ret, ss, ss[8]=='X'?"yes":"NO!");
ret=snprintf(ss, 8, "1234%s","56789"); fprintf(stderr,"[BAD] RET=%d,
SS='%s' X OK? %s\n", ret, ss, ss[8]=='X'?"yes":"NO!");
ret=snprintf(ss, 8, "1234%s","567890"); fprintf(stderr,"[BAD] RET=%d,
SS='%s' X OK? %s\n", ret, ss, ss[8]=='X'?"yes":"NO!");
}
..under linux, the correct output is given:
[OK] RET=6, SS='123456' X OK? yes
[OK] RET=7, SS='1234567' X OK? yes
[BAD] RET=8, SS='1234567' X OK? yes
[BAD] RET=9, SS='1234567' X OK? yes
[BAD] RET=10, SS='1234567' X OK? yes
..when the boundary limit is reached, the string remains null terminated.
BUT under windows it leaves the string unterminated (apparently as
documented!),
as the "XY" shown in the following output makes clear:
[OK] RET=6, SS='123456' X OK? yes
[OK] RET=7, SS='1234567' X OK? yes
[BAD] RET=8, SS='12345678XY' X OK? yes <-- argh -- XY should not show up.
[BAD] RET=-1, SS='12345678XY' X OK? yes <-- argh
[BAD] RET=-1, SS='12345678XY' X OK? yes <-- argh
Their docs do recommend using _snprintf_s() instead of _snprintf(),
which is supposedly their 'secure' version of _snprintf().
Well, I tried that, but then the above program /crashes/..!
Reading the docs, I can think of no reason why it should crash.
Apparently their 'secure' function is worse than the insecure one.
[..]Seems the "right" solution is as follows, I'm not sure I see
a "macro" way to hide this, since the argument list is different
and this is a "varargs" type function:
#ifdef _WIN32
_snprintf_s(nametmp, sizeof(nametmp), _TRUNCATE, "%s_%d", name.c_str(),
id); // microsoft's _sprintf() doesn't truncate(!) use _sprintf_s()
instead
#else
snprintf(nametmp, sizeof(nametmp), "%s_%d", name.c_str(), id);
#endif
That extra "_TRUNCATE" argument before the format string being the
issue that seems to prevent using a macro to hide this.
_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev