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