255e5e
From 2a4ee2d1702febccc0d81c1724eb61cb654ed72f Mon Sep 17 00:00:00 2001
255e5e
From: jmaloy <jmaloy@redhat.com>
255e5e
Date: Thu, 14 May 2020 21:13:09 +0100
255e5e
Subject: [PATCH 1/6] util: add slirp_fmt() helpers
255e5e
MIME-Version: 1.0
255e5e
Content-Type: text/plain; charset=UTF-8
255e5e
Content-Transfer-Encoding: 8bit
255e5e
255e5e
RH-Author: jmaloy <jmaloy@redhat.com>
255e5e
Message-id: <20200514211314.1534001-2-jmaloy@redhat.com>
255e5e
Patchwork-id: 96585
255e5e
O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 1/6] util: add slirp_fmt() helpers
255e5e
Bugzilla: 1834477
255e5e
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
255e5e
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
255e5e
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
255e5e
255e5e
From: Marc-André Lureau <marcandre.lureau@redhat.com>
255e5e
255e5e
Various calls to snprintf() in libslirp assume that snprintf() returns
255e5e
"only" the number of bytes written (excluding terminating NUL).
255e5e
255e5e
https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04
255e5e
255e5e
"Upon successful completion, the snprintf() function shall return the
255e5e
number of bytes that would be written to s had n been sufficiently
255e5e
large excluding the terminating null byte."
255e5e
255e5e
Introduce slirp_fmt() that handles several pathological cases the
255e5e
way libslirp usually expect:
255e5e
255e5e
- treat error as fatal (instead of silently returning -1)
255e5e
255e5e
- fmt0() will always \0 end
255e5e
255e5e
- return the number of bytes actually written (instead of what would
255e5e
  have been written, which would usually result in OOB later), including
255e5e
  the ending \0 for fmt0()
255e5e
255e5e
- warn if truncation happened (instead of ignoring)
255e5e
255e5e
  Other less common cases can still be handled with strcpy/snprintf() etc.
255e5e
255e5e
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
255e5e
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
255e5e
Message-Id: <20200127092414.169796-2-marcandre.lureau@redhat.com>
255e5e
255e5e
(cherry-picked from libslirp commit 30648c03b27fb8d9611b723184216cd3174b6775)
255e5e
Manual cherry pick, since there is no util.c file in this code version.
255e5e
Instead, we add the new functions to the file misc.c.
255e5e
255e5e
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
255e5e
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
255e5e
---
255e5e
 slirp/misc.c  | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
255e5e
 slirp/slirp.h |  2 ++
255e5e
 2 files changed, 64 insertions(+)
255e5e
255e5e
diff --git a/slirp/misc.c b/slirp/misc.c
255e5e
index 260187b..035b9ab 100644
255e5e
--- a/slirp/misc.c
255e5e
+++ b/slirp/misc.c
255e5e
@@ -293,3 +293,65 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
255e5e
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
255e5e
     }
255e5e
 }
255e5e
+
255e5e
+static int slirp_vsnprintf(char *str, size_t size,
255e5e
+                           const char *format, va_list args)
255e5e
+{
255e5e
+    int rv = vsnprintf(str, size, format, args);
255e5e
+
255e5e
+    if (rv < 0) {
255e5e
+        g_error("vsnprintf() failed: %s", g_strerror(errno));
255e5e
+    }
255e5e
+
255e5e
+    return rv;
255e5e
+}
255e5e
+
255e5e
+/*
255e5e
+ * A snprintf()-like function that:
255e5e
+ * - returns the number of bytes written (excluding optional \0-ending)
255e5e
+ * - dies on error
255e5e
+ * - warn on truncation
255e5e
+ */
255e5e
+int slirp_fmt(char *str, size_t size, const char *format, ...)
255e5e
+{
255e5e
+    va_list args;
255e5e
+    int rv;
255e5e
+
255e5e
+    va_start(args, format);
255e5e
+    rv = slirp_vsnprintf(str, size, format, args);
255e5e
+    va_end(args);
255e5e
+
255e5e
+    if (rv > size) {
255e5e
+        g_critical("vsnprintf() truncation");
255e5e
+    }
255e5e
+
255e5e
+    return MIN(rv, size);
255e5e
+}
255e5e
+
255e5e
+/*
255e5e
+ * A snprintf()-like function that:
255e5e
+ * - always \0-end (unless size == 0)
255e5e
+ * - returns the number of bytes actually written, including \0 ending
255e5e
+ * - dies on error
255e5e
+ * - warn on truncation
255e5e
+ */
255e5e
+int slirp_fmt0(char *str, size_t size, const char *format, ...)
255e5e
+{
255e5e
+    va_list args;
255e5e
+    int rv;
255e5e
+
255e5e
+    va_start(args, format);
255e5e
+    rv = slirp_vsnprintf(str, size, format, args);
255e5e
+    va_end(args);
255e5e
+
255e5e
+    if (rv >= size) {
255e5e
+        g_critical("vsnprintf() truncation");
255e5e
+        if (size > 0)
255e5e
+            str[size - 1] = '\0';
255e5e
+        rv = size;
255e5e
+    } else {
255e5e
+        rv += 1; /* include \0 */
255e5e
+    }
255e5e
+
255e5e
+    return rv;
255e5e
+}
255e5e
diff --git a/slirp/slirp.h b/slirp/slirp.h
255e5e
index 06febfc..49b8c2c 100644
255e5e
--- a/slirp/slirp.h
255e5e
+++ b/slirp/slirp.h
255e5e
@@ -292,5 +292,7 @@ uint8_t tcp_tos(struct socket *);
255e5e
 int tcp_emu(struct socket *, struct mbuf *);
255e5e
 int tcp_ctl(struct socket *);
255e5e
 struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
255e5e
+int slirp_fmt(char *str, size_t size, const char *format, ...);
255e5e
+int slirp_fmt0(char *str, size_t size, const char *format, ...);
255e5e
 
255e5e
 #endif
255e5e
-- 
255e5e
1.8.3.1
255e5e