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