bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-gnulib] Re: snprintf


From: Simon Josefsson
Subject: [Bug-gnulib] Re: snprintf
Date: Tue, 21 Sep 2004 21:43:06 +0200
User-agent: Gnus/5.110003 (No Gnus v0.3) Emacs/21.3.50 (gnu/linux)

Bruno Haible <address@hidden> writes:

> Simon Josefsson wrote:
>> I have not really tested it, but that
>> will be easier once it is integrated.
>
> Huh? You can run gnulib-tool in your local, modified gnulib checkout.
> You don't need to assume something is in CVS before you can test it.

Yes, I did that, but I'm not sure that is called real testing, since
my system has snprintf.  Really tested would be compiled on many
platforms, and testing code that uses the new code.

>> +    memcpy (str, out, MIN (len, size));
>
> That should be  len + 1  instead of len, no?

I think so, yes, thanks.

Further, it seems snprintf should always zero terminate the string,
even when it is truncated.  The old code didn't do that.  New
snprintf.c below.

> Other than that, I'm a little lost why anyone would need snprintf, when
> he already has asnprintf in the library. Sure, snprintf is better than
> sprintf, to avoid buffer overflows in jpeg displaying libraries :-)
> But rather than using a size-limited buffer and then use a temporary
> malloc-allocated buffer for filling the size-limited buffer, why would
> you not use a malloc-allocated buffer for the result? Avoiding
> arbitrary limits is one of the recommendations RMS gives in the GNU
> standards
>      "Unix programs " [actually that's BSD style] " often have static
>       tables or fixed-size strings, which make for arbitrary limits; use
>       dynamic allocation instead."

Some reasons:

1) It would be harder to argue that asnprintf is a "system component",
   as far as licensing goes.  It is easier to argue that snprintf is a
   system component, since it should be on good platforms.

2) Sometimes you want to avoid memory allocation.  Especially when
   crafting together strings that should go out on the network, where
   strings sometimes are typically specified to a fixed length.

But I'll consider using asnprintf.  This was for GnuTLS, which hasn't
used anything from gnulib before, so the code probably has several
calls to snprintf.

Thanks,
Simon

Index: lib/snprintf.c
===================================================================
RCS file: lib/snprintf.c
diff -N lib/snprintf.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/snprintf.c      21 Sep 2004 19:38:00 -0000
@@ -0,0 +1,55 @@
+/* Formatted output to strings.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Written by Simon Josefsson.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Get specification.  */
+#include "snprintf.h"
+
+/* Get vasnprintf.  */
+#include "vasnprintf.h"
+
+/* Get MIN. */
+#include <minmax.h>
+
+/* Print formatted output to string STR.  Similar to sprintf, but
+   additional length SIZE limit how much is written into STR.  Returns
+   string length of formatted string (which may be larger than SIZE).
+   STR may be NULL, in which case nothing will be written.  On error,
+   return a negative value. */
+int
+snprintf (char *str, size_t size, const char *format, ...)
+{
+  size_t len;
+  char *out = vasnprintf (NULL, &len, format, args);
+
+  if (!out)
+    return -1;
+
+  if (str)
+    {
+      memcpy (str, out, MIN (len + 1, size));
+      str[size - 1] = '\0';
+    }
+
+  free (out);
+
+  return len;
+}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]