73f313
From cf712371da839a8655506aacc2908f7ffc3988ab Mon Sep 17 00:00:00 2001
73f313
From: jmaloy <jmaloy@redhat.com>
73f313
Date: Thu, 13 Feb 2020 21:08:17 +0100
73f313
Subject: [PATCH 1/6] util: add slirp_fmt() helpers
73f313
MIME-Version: 1.0
73f313
Content-Type: text/plain; charset=UTF-8
73f313
Content-Transfer-Encoding: 8bit
73f313
73f313
Message-id: <20200213210818.9090-2-jmaloy@redhat.com>
73f313
Patchwork-id: 93831
73f313
O-Subject: [RHEL-7.8 qemu-kvm PATCH 1/2] util: add slirp_fmt() helpers
73f313
Bugzilla: 1800515
73f313
RH-Acked-by: Maxim Levitsky <mlevitsk@redhat.com>
73f313
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
73f313
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
73f313
73f313
From: Marc-André Lureau <marcandre.lureau@redhat.com>
73f313
73f313
Various calls to snprintf() in libslirp assume that snprintf() returns
73f313
"only" the number of bytes written (excluding terminating NUL).
73f313
73f313
https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04
73f313
73f313
"Upon successful completion, the snprintf() function shall return the
73f313
number of bytes that would be written to s had n been sufficiently
73f313
large excluding the terminating null byte."
73f313
73f313
Introduce slirp_fmt() that handles several pathological cases the
73f313
way libslirp usually expect:
73f313
73f313
- treat error as fatal (instead of silently returning -1)
73f313
73f313
- fmt0() will always \0 end
73f313
73f313
- return the number of bytes actually written (instead of what would
73f313
  have been written, which would usually result in OOB later), including
73f313
  the ending \0 for fmt0()
73f313
73f313
- warn if truncation happened (instead of ignoring)
73f313
73f313
  Other less common cases can still be handled with strcpy/snprintf() etc.
73f313
73f313
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
73f313
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
73f313
Message-Id: <20200127092414.169796-2-marcandre.lureau@redhat.com>
73f313
73f313
Manually re-adapted from 30648c03b27fb8d9611b723184216cd3174b6775
73f313
since cerry-pick cannot be used here. There is no util.c file in this
73f313
code version, so we add the two new functions as static functions in
73f313
the file where they are going to be used.
73f313
73f313
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
73f313
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
73f313
---
73f313
 slirp/tcp_subr.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
73f313
 1 file changed, 65 insertions(+)
73f313
73f313
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
73f313
index 19e2245..e83575e 100644
73f313
--- a/slirp/tcp_subr.c
73f313
+++ b/slirp/tcp_subr.c
73f313
@@ -44,6 +44,9 @@
73f313
 /* Don't do rfc1323 performance enhancements */
73f313
 #define TCP_DO_RFC1323 0
73f313
 
73f313
+static int slirp_fmt(char *str, size_t size, const char *format, ...);
73f313
+static int slirp_fmt0(char *str, size_t size, const char *format, ...);
73f313
+
73f313
 /*
73f313
  * Tcp initialization
73f313
  */
73f313
@@ -935,3 +938,65 @@ int tcp_ctl(struct socket *so)
73f313
     sb->sb_wptr += sb->sb_cc;
73f313
     return 0;
73f313
 }
73f313
+
73f313
+static int slirp_vsnprintf(char *str, size_t size,
73f313
+                           const char *format, va_list args)
73f313
+{
73f313
+    int rv = vsnprintf(str, size, format, args);
73f313
+
73f313
+    if (rv < 0) {
73f313
+        g_error("vsnprintf() failed: %s", g_strerror(errno));
73f313
+    }
73f313
+
73f313
+    return rv;
73f313
+}
73f313
+
73f313
+/*
73f313
+ * A snprintf()-like function that:
73f313
+ * - returns the number of bytes written (excluding optional \0-ending)
73f313
+ * - dies on error
73f313
+ * - warn on truncation
73f313
+ */
73f313
+static int slirp_fmt(char *str, size_t size, const char *format, ...)
73f313
+{
73f313
+    va_list args;
73f313
+    int rv;
73f313
+
73f313
+    va_start(args, format);
73f313
+    rv = slirp_vsnprintf(str, size, format, args);
73f313
+    va_end(args);
73f313
+
73f313
+    if (rv > size) {
73f313
+        g_critical("vsnprintf() truncation");
73f313
+    }
73f313
+
73f313
+    return MIN(rv, size);
73f313
+}
73f313
+
73f313
+/*
73f313
+ * A snprintf()-like function that:
73f313
+ * - always \0-end (unless size == 0)
73f313
+ * - returns the number of bytes actually written, including \0 ending
73f313
+ * - dies on error
73f313
+ * - warn on truncation
73f313
+ */
73f313
+static int slirp_fmt0(char *str, size_t size, const char *format, ...)
73f313
+{
73f313
+    va_list args;
73f313
+    int rv;
73f313
+
73f313
+    va_start(args, format);
73f313
+    rv = slirp_vsnprintf(str, size, format, args);
73f313
+    va_end(args);
73f313
+
73f313
+    if (rv >= size) {
73f313
+        g_critical("vsnprintf() truncation");
73f313
+        if (size > 0)
73f313
+            str[size - 1] = '\0';
73f313
+        rv = size;
73f313
+    } else {
73f313
+        rv += 1; /* include \0 */
73f313
+    }
73f313
+
73f313
+    return rv;
73f313
+}
73f313
-- 
73f313
1.8.3.1
73f313