summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2011-06-21 14:09:32 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2011-09-21 11:25:48 +0100
commit7fc9c026669976463adcd1e02ad19c582ed27289 (patch)
tree0351d23409734f4d227bc501277e9c717d4f1480
parent029ecdf40268b1c0db04bb617f067487719bf251 (diff)
downloaddbus-7fc9c026669976463adcd1e02ad19c582ed27289.tar.gz
Cope with platforms whose vsnprintf violates both POSIX and C99
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=11668 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk>
-rw-r--r--dbus/dbus-sysdeps-unix.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 171977d3..f51f6fcb 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -3021,14 +3021,60 @@ _dbus_full_duplex_pipe (int *fd1,
*
* @param format a printf-style format string
* @param args arguments for the format string
- * @returns length of the given format string and args
+ * @returns length of the given format string and args, or -1 if no memory
*/
int
_dbus_printf_string_upper_bound (const char *format,
va_list args)
{
- char c;
- return vsnprintf (&c, 1, format, args);
+ char static_buf[1024];
+ int bufsize = sizeof (static_buf);
+ int len;
+
+ len = vsnprintf (static_buf, bufsize, format, args);
+
+ /* If vsnprintf() returned non-negative, then either the string fits in
+ * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
+ * returns the number of characters that were needed, or this OS returns the
+ * truncated length.
+ *
+ * We ignore the possibility that snprintf might just ignore the length and
+ * overrun the buffer (64-bit Solaris 7), because that's pathological.
+ * If your libc is really that bad, come back when you have a better one. */
+ if (len == bufsize)
+ {
+ /* This could be the truncated length (Tru64 and IRIX have this bug),
+ * or the real length could be coincidentally the same. Which is it?
+ * If vsnprintf returns the truncated length, we'll go to the slow
+ * path. */
+ if (vsnprintf (static_buf, 1, format, args) == 1)
+ len = -1;
+ }
+
+ /* If vsnprintf() returned negative, we have to do more work.
+ * HP-UX returns negative. */
+ while (len < 0)
+ {
+ char *buf;
+
+ bufsize *= 2;
+
+ buf = dbus_malloc (bufsize);
+
+ if (buf == NULL)
+ return -1;
+
+ len = vsnprintf (buf, bufsize, format, args);
+ dbus_free (buf);
+
+ /* If the reported length is exactly the buffer size, round up to the
+ * next size, in case vsnprintf has been returning the truncated
+ * length */
+ if (len == bufsize)
+ len = -1;
+ }
+
+ return len;
}
/**