Re: Possible testing case of snprintf.

2020-02-09 Thread Tim Rühsen
On 09.02.20 15:44, Mats Erik Andersson wrote:
> Hello there!
> 
> This note has its origin in a report received at bug-inetutils.
> The following test code for snprintf() is a simplyfied detection
> I have implemented as a warning-only test in Gnu Inetutils.
> My point is that Linux/glibc and kfreebsd/glibc triggers this
> warning, but OpenSolaris, OpenIndiana, FreeBSD, OpenBSD, NetBSD,
> and DragonflyBSD do not! Reading the replacement code for the
> Gnulib module snprintf, neither would your function, should it
> undergo the test. In conclusion, this is a case where the native
> glibc function snprintf() behaves worse than does your replacement.
> 
>   #define MESSAGE   "try a fool"
>   #define WRONG_MESSAGE "fool"
> 
>   char msg[sizeof (MESSAGE)] = "try a ";
> 
>   snprintf (msg, sizeof (msg), "%s%s", msg, WRONG_MESSAGE);
> 
>   if (!strcmp (msg, WRONG_MESSAGE))
> printf ("Warning! snprintf got confused!\n");
> 
> Observe that `msg' is target, as well as source. POSIX mentions
> nothing about such a use case, but glibc will produce "fool",
> whereas all BSD unices as well as OpenSolaris descendants will
> produce "try a fool". Tacitly, POSIX would probably cry out
> a statement like "Undefined"!

s(n)printf declaration uses the restrict keyword. That basically means
that each of the pointers in the arguments points to the same block of
memory.

gcc -Wall tells you so (gcc 8 and upwards):
$ gcc -Wall msg.c -o msg
msg.c: In function ‘main’:
msg.c:11:13: warning: passing argument 1 to restrict-qualified parameter
aliases with argument 4 [-Wrestrict]
   11 |   snprintf (msg, sizeof (msg), "%s%s", msg, WRONG_MESSAGE);
  | ^~~~~~
msg.c:11:35: warning: ‘%s’ directive output may be truncated writing 4
bytes into a region of size between 1 and 11 [-Wformat-truncation=]
   11 |   snprintf (msg, sizeof (msg), "%s%s", msg, WRONG_MESSAGE);
  |   ^~
msg.c:11:3: note: ‘snprintf’ output between 5 and 15 bytes into a
destination of size 11
   11 |   snprintf (msg, sizeof (msg), "%s%s", msg, WRONG_MESSAGE);
  |   ^~~~

Except in rare cases, compiler warnings indicate that the programmer is
wrong. Turn them all (well, almost all) on !

Regards, Tim



signature.asc
Description: OpenPGP digital signature


Possible testing case of snprintf.

2020-02-09 Thread Mats Erik Andersson
Hello there!

This note has its origin in a report received at bug-inetutils.
The following test code for snprintf() is a simplyfied detection
I have implemented as a warning-only test in Gnu Inetutils.
My point is that Linux/glibc and kfreebsd/glibc triggers this
warning, but OpenSolaris, OpenIndiana, FreeBSD, OpenBSD, NetBSD,
and DragonflyBSD do not! Reading the replacement code for the
Gnulib module snprintf, neither would your function, should it
undergo the test. In conclusion, this is a case where the native
glibc function snprintf() behaves worse than does your replacement.

  #define MESSAGE   "try a fool"
  #define WRONG_MESSAGE "fool"

  char msg[sizeof (MESSAGE)] = "try a ";

  snprintf (msg, sizeof (msg), "%s%s", msg, WRONG_MESSAGE);

  if (!strcmp (msg, WRONG_MESSAGE))
printf ("Warning! snprintf got confused!\n");

Observe that `msg' is target, as well as source. POSIX mentions
nothing about such a use case, but glibc will produce "fool",
whereas all BSD unices as well as OpenSolaris descendants will
produce "try a fool". Tacitly, POSIX would probably cry out
a statement like "Undefined"!

It is my opinion that this discrepancies should at least be documented
in 'snprintf.texi', were you not to take matter so far as to include
this as some sort of test, after due elaboration.

Gnu Inetutils uses legacy code from BSD4.4, where the related use
is present and did not cause troubles, but as the recent report
submitted to us, the code does produce portability issues when
brought to glibc. It has taken a long time to discover this state
of affaires, but now it has surfaced!

On behalf of Gnu Inetutils,

  Mats Erik Andersson.