22c213
From 5dc50c6bca059a9cda6677b1fd0187df1de78ed7 Mon Sep 17 00:00:00 2001
22c213
From: jmaloy <jmaloy@redhat.com>
22c213
Date: Thu, 13 Feb 2020 15:50:48 +0000
22c213
Subject: [PATCH 2/7] util: add slirp_fmt() helpers
22c213
MIME-Version: 1.0
22c213
Content-Type: text/plain; charset=UTF-8
22c213
Content-Transfer-Encoding: 8bit
22c213
22c213
RH-Author: jmaloy <jmaloy@redhat.com>
22c213
Message-id: <20200213155049.3936-2-jmaloy@redhat.com>
22c213
Patchwork-id: 93824
22c213
O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 1/2] util: add slirp_fmt() helpers
22c213
Bugzilla: 1798994
22c213
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
22c213
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22c213
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
22c213
22c213
From: Marc-André Lureau <marcandre.lureau@redhat.com>
22c213
22c213
Various calls to snprintf() in libslirp assume that snprintf() returns
22c213
"only" the number of bytes written (excluding terminating NUL).
22c213
22c213
https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04
22c213
22c213
"Upon successful completion, the snprintf() function shall return the
22c213
number of bytes that would be written to s had n been sufficiently
22c213
large excluding the terminating null byte."
22c213
22c213
Introduce slirp_fmt() that handles several pathological cases the
22c213
way libslirp usually expect:
22c213
22c213
- treat error as fatal (instead of silently returning -1)
22c213
22c213
- fmt0() will always \0 end
22c213
22c213
- return the number of bytes actually written (instead of what would
22c213
have been written, which would usually result in OOB later), including
22c213
the ending \0 for fmt0()
22c213
22c213
- warn if truncation happened (instead of ignoring)
22c213
22c213
Other less common cases can still be handled with strcpy/snprintf() etc.
22c213
22c213
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
22c213
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
22c213
Message-Id: <20200127092414.169796-2-marcandre.lureau@redhat.com>
22c213
(cherry picked from libslirp commit 30648c03b27fb8d9611b723184216cd3174b6775)
22c213
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
22c213
22c213
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
22c213
---
22c213
 slirp/src/util.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22c213
 slirp/src/util.h |  3 +++
22c213
 2 files changed, 65 insertions(+)
22c213
22c213
diff --git a/slirp/src/util.c b/slirp/src/util.c
22c213
index e596087..e3b6257 100644
22c213
--- a/slirp/src/util.c
22c213
+++ b/slirp/src/util.c
22c213
@@ -364,3 +364,65 @@ void slirp_pstrcpy(char *buf, int buf_size, const char *str)
22c213
     }
22c213
     *q = '\0';
22c213
 }
22c213
+
22c213
+static int slirp_vsnprintf(char *str, size_t size,
22c213
+                           const char *format, va_list args)
22c213
+{
22c213
+    int rv = vsnprintf(str, size, format, args);
22c213
+
22c213
+    if (rv < 0) {
22c213
+        g_error("vsnprintf() failed: %s", g_strerror(errno));
22c213
+    }
22c213
+
22c213
+    return rv;
22c213
+}
22c213
+
22c213
+/*
22c213
+ * A snprintf()-like function that:
22c213
+ * - returns the number of bytes written (excluding optional \0-ending)
22c213
+ * - dies on error
22c213
+ * - warn on truncation
22c213
+ */
22c213
+int slirp_fmt(char *str, size_t size, const char *format, ...)
22c213
+{
22c213
+    va_list args;
22c213
+    int rv;
22c213
+
22c213
+    va_start(args, format);
22c213
+    rv = slirp_vsnprintf(str, size, format, args);
22c213
+    va_end(args);
22c213
+
22c213
+    if (rv > size) {
22c213
+        g_critical("vsnprintf() truncation");
22c213
+    }
22c213
+
22c213
+    return MIN(rv, size);
22c213
+}
22c213
+
22c213
+/*
22c213
+ * A snprintf()-like function that:
22c213
+ * - always \0-end (unless size == 0)
22c213
+ * - returns the number of bytes actually written, including \0 ending
22c213
+ * - dies on error
22c213
+ * - warn on truncation
22c213
+ */
22c213
+int slirp_fmt0(char *str, size_t size, const char *format, ...)
22c213
+{
22c213
+    va_list args;
22c213
+    int rv;
22c213
+
22c213
+    va_start(args, format);
22c213
+    rv = slirp_vsnprintf(str, size, format, args);
22c213
+    va_end(args);
22c213
+
22c213
+    if (rv >= size) {
22c213
+        g_critical("vsnprintf() truncation");
22c213
+        if (size > 0)
22c213
+            str[size - 1] = '\0';
22c213
+        rv = size;
22c213
+    } else {
22c213
+        rv += 1; /* include \0 */
22c213
+    }
22c213
+
22c213
+    return rv;
22c213
+}
22c213
diff --git a/slirp/src/util.h b/slirp/src/util.h
22c213
index 3c6223c..0558dfc 100644
22c213
--- a/slirp/src/util.h
22c213
+++ b/slirp/src/util.h
22c213
@@ -177,4 +177,7 @@ static inline int slirp_socket_set_fast_reuse(int fd)
22c213
 
22c213
 void slirp_pstrcpy(char *buf, int buf_size, const char *str);
22c213
 
22c213
+int slirp_fmt(char *str, size_t size, const char *format, ...);
22c213
+int slirp_fmt0(char *str, size_t size, const char *format, ...);
22c213
+
22c213
 #endif
22c213
-- 
22c213
1.8.3.1
22c213