Support non-standard vsnprintf() return code
authorAlexander Barton <alex@barton.de>
Sat, 4 Jan 2014 22:57:05 +0000 (23:57 +0100)
committerAlexander Barton <alex@barton.de>
Sat, 4 Jan 2014 22:57:05 +0000 (23:57 +0100)
C99 states that vsnprintf() "returns the number of characters that
would have been printed if the n were unlimited"; but according to the
Linux manual page "glibc until 2.0.6 would return -1 when the output
was truncated" -- so we have to handle both cases ...

src/ngircd/conn.c
src/portab/portabtest.c

index 3f447c61ec367916f528f13a9da0852ac83eb0f4..fef568e4a17094b2513b9fbc9a722ed18a83f3d2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
  *
  * 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
@@ -984,6 +984,7 @@ va_dcl
        size_t len;
        bool ok;
        va_list ap;
+       int r;
 
        assert( Idx > NONE );
        assert( Format != NULL );
@@ -993,7 +994,8 @@ va_dcl
 #else
        va_start( ap );
 #endif
-       if (vsnprintf( buffer, COMMAND_LEN - 2, Format, ap ) >= COMMAND_LEN - 2 ) {
+       r = vsnprintf(buffer, COMMAND_LEN - 2, Format, ap);
+       if (r >= COMMAND_LEN - 2 || r == -1) {
                /*
                 * The string that should be written to the socket is longer
                 * than the allowed size of COMMAND_LEN bytes (including both
@@ -1014,6 +1016,13 @@ va_dcl
                 * an other server only routing the message!), so the only
                 * option left is to shorten the string and to hope that the
                 * result is still somewhat useful ...
+                *
+                * Note:
+                * C99 states that vsnprintf() "returns the number of characters
+                * that would have been printed if the n were unlimited"; but
+                * according to the Linux manual page "glibc until 2.0.6 would
+                * return -1 when the output was truncated" -- so we have to
+                * handle both cases ...
                 *                                                   -alex-
                 */
 
index 9e6bd228bae0df847ab6d32fc52401d9bfc0aa37..b104739e26b64c473c618873fd0d27eb97f0b5ed 100644 (file)
@@ -139,16 +139,35 @@ va_dcl
 {
        char str[5];
        va_list ap;
+       int r;
 
 #ifdef PROTOTYPES
        va_start(ap, Format);
 #else
        va_start(ap);
 #endif
-       if (vsnprintf(str, sizeof(str), Format, ap) != Len)
-               Panic("vsnprintf return code");
+       r = vsnprintf(str, sizeof(str), Format, ap);
        va_end(ap);
-
+       if (r != Len) {
+               /* C99 states that vsnprintf() "returns the number of
+                * characters that would have been printed if the n were
+                * unlimited", but according to the Linux manual page "glibc
+                * until 2.0.6 would return -1 when the output was truncated",
+                * and other implementations (libUTIL on A/UX) even return the
+                * number of characters processed ... so we only test our own
+                * implementation and warn on errors otherwise :-/ */
+#ifdef HAVE_VSNPRINTF
+               fprintf(stderr,
+                       "\n ** WARNING: The vsnprintf() function of this system isn't standard\n");
+               fprintf(stderr,
+                       " ** conformant and returns a WRONG result: %d (should be %d)! The test\n",
+                       r, Len);
+               fprintf(stderr,
+                       " ** result has been ignored but may lead to errors during execution!\n\n");
+#else
+               Panic("vsnprintf return code");
+#endif
+       }
        if (str[4] != '\0')
                Panic("vsnprintf NULL byte");
        if (strlen(str) != 4)