]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Fix strnvis() and strnunvis() NetBSD ABI break
authorGuillem Jover <guillem@hadrons.org>
Tue, 22 May 2018 11:50:44 +0000 (13:50 +0200)
committerGuillem Jover <guillem@hadrons.org>
Tue, 22 May 2018 14:07:42 +0000 (16:07 +0200)
The NetBSD implementations have different prototypes to the ones coming
from OpenBSD, which will break builds, and have caused segfaults at
run-time. We provide now both interfaces with different prototypes as
different version nodes allow selecting them at compile-time, defaulting
for now to the OpenBSD one to avoid build-time breakage, while emitting
a compile-time warning. Later on, in 0.10.0, we will be switching the
compile-time default to the NetBSD version.

Ref: http://gnats.netbsd.org/44977
Fixes: https://bugs.debian.org/899282
include/bsd/vis.h
src/libbsd.map
src/unvis.c
src/vis.c
test/.gitignore
test/Makefile.am
test/vis-openbsd.c [new file with mode: 0644]
test/vis.c [new file with mode: 0644]

index d8b6635a16dfe2519cdfe46838473642847f4fa9..84102b2c1c18f9ea97de2e587f593491009c3973 100644 (file)
 #include <bsd/sys/cdefs.h>
 #endif
 
+/*
+ * NetBSD added an strnvis and unfortunately made it incompatible with the
+ * existing one in OpenBSD and Freedesktop's libbsd (the former having existed
+ * for over ten years). Despite this incompatibility being reported during
+ * development (see http://gnats.netbsd.org/44977) they still shipped it.
+ * Even more unfortunately FreeBSD and later MacOS picked up this incompatible
+ * implementation.
+ *
+ * Provide both implementations and default for now on the historical one to
+ * avoid breakage, we will switch to the NetBSD one in libbsd 0.10.0 or so.
+ * Define LIBBSD_NETBSD_VIS to switch to the NetBSD one now.
+ */
+#ifndef LIBBSD_NETBSD_VIS
+#warning "NetBSD added incompatible strnvis() and strnunvis(), please see <bsd/vis.h> for more detils."
+#endif
+
 __BEGIN_DECLS
 char   *vis(char *, int, int, int);
 char   *nvis(char *, size_t, int, int, int);
@@ -97,7 +113,14 @@ char        *snvis(char *, size_t, int, int, int, const char *);
 
 int    strvis(char *, const char *, int);
 int    stravis(char **, const char *, int);
-int    strnvis(char *, size_t, const char *, int);
+#ifdef LIBBSD_NETBSD_VIS
+/* NetBSD prototype. */
+int    LIBBSD_REDIRECT(strnvis, (char *, size_t, const char *, int),
+                        strnvis_netbsd);
+#else
+/* OpenBSD prototype (current default). */
+int    strnvis(char *, const char *, size_t, int);
+#endif
 
 int    strsvis(char *, const char *, int, const char *);
 int    strsnvis(char *, size_t, const char *, int, const char *);
@@ -112,7 +135,14 @@ int        strsenvisx(char *, size_t, const char *, size_t , int, const char *,
     int *);
 
 int    strunvis(char *, const char *);
-int    strnunvis(char *, size_t, const char *);
+#ifdef LIBBSD_NETBSD_VIS
+/* NetBSD prototype. */
+int    LIBBSD_REDIRECT(strnunvis, (char *, size_t, const char *),
+                        strnunvis_netbsd);
+#else
+/* OpenBSD prototype (current default). */
+ssize_t        strnunvis(char *, const char *, size_t);
+#endif
 
 int    strunvisx(char *, const char *, int);
 int    strnunvisx(char *, size_t, const char *, int);
index 98b95ce40034e71e59cf11c2cbf049a6fde8b3e5..ce360407000d7ce77341e491cd31243e8a5f6d86 100644 (file)
@@ -160,3 +160,11 @@ LIBBSD_0.9 {
     strsvisx;
     svis;
 } LIBBSD_0.8;
+
+LIBBSD_0.9.1 {
+    /* The strnvis() and strnunvis() symbols changed prototype to match
+     * the NetBSD implementation. Provided as versioned nodes in 0.9.1, and
+     * exposed here explicitly so that we can redirect at compile-time. */
+    strnvis_netbsd;
+    strnunvis_netbsd;
+} LIBBSD_0.9;
index e16bd50d3cd7cea01eb70301dce36bea30d188b9..94e3e7aac814e6df411e238f9838aaa9809935e8 100644 (file)
 #include <stdint.h>
 #include <stdio.h>
 #include <errno.h>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcpp"
 #include <vis.h>
+#pragma GCC diagnostic pop
 
 #ifdef __weak_alias
 __weak_alias(strnunvisx,_strnunvisx)
@@ -543,8 +546,30 @@ strunvis(char *dst, const char *src)
        return strnunvisx(dst, (size_t)~0, src, 0);
 }
 
+/*
+ * NetBSD added an strnvis and unfortunately made it incompatible with the
+ * existing one in OpenBSD and Freedesktop's libbsd (the former having existed
+ * for over ten years). Despite this incompatibility being reported during
+ * development (see http://gnats.netbsd.org/44977) they still shipped it.
+ * Even more unfortunately FreeBSD and later MacOS picked up this incompatible
+ * implementation.
+ *
+ * Provide both implementations and default for now on the historical one to
+ * avoid breakage, we will switch to the NetBSD one in libbsd 0.10.0 or so.
+ *
+ * OpenBSD, 2001: strnunvis(char *dst, const char *src, size_t dlen);
+ * NetBSD: 2012,  strnunvis(char *dst, size_t dlen, const char *src);
+ */
+ssize_t
+strnunvis_openbsd(char *dst, const char *src, size_t dlen)
+{
+       return strnunvisx(dst, dlen, src, 0);
+}
+__asm__(".symver strnunvis_openbsd,strnunvis@@LIBBSD_0.2");
+
 int
-strnunvis(char *dst, size_t dlen, const char *src)
+strnunvis_netbsd(char *dst, size_t dlen, const char *src)
 {
        return strnunvisx(dst, dlen, src, 0);
 }
+__asm__(".symver strnunvis_netbsd,strnunvis@LIBBSD_0.9.1");
index 559943935a19657c0463191d36b63ec980999821..c2cd2d886735cd034ae7a8c7e291dea424b154f3 100644 (file)
--- a/src/vis.c
+++ b/src/vis.c
 #include <sys/param.h>
 
 #include <assert.h>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcpp"
 #include <vis.h>
+#pragma GCC diagnostic pop
 #include <errno.h>
 #include <stdlib.h>
 #include <wchar.h>
@@ -701,11 +704,33 @@ strvis(char *mbdst, const char *mbsrc, int flags)
        return istrsenvisxl(&mbdst, NULL, mbsrc, flags, "", NULL);
 }
 
+/*
+ * NetBSD added an strnvis and unfortunately made it incompatible with the
+ * existing one in OpenBSD and Freedesktop's libbsd (the former having existed
+ * for over ten years). Despite this incompatibility being reported during
+ * development (see http://gnats.netbsd.org/44977) they still shipped it.
+ * Even more unfortunately FreeBSD and later MacOS picked up this incompatible
+ * implementation.
+ *
+ * Provide both implementations and default for now on the historical one to
+ * avoid breakage, we will switch to the NetBSD one in libbsd 0.10.0 or so.
+ *
+ * OpenBSD, 2001: strnvis(char *dst, const char *src, size_t dlen, int flag);
+ * NetBSD: 2012,  strnvis(char *dst, size_t dlen, const char *src, int flag);
+ */
+int
+strnvis_openbsd(char *mbdst, const char *mbsrc, size_t dlen, int flags)
+{
+       return istrsenvisxl(&mbdst, &dlen, mbsrc, flags, "", NULL);
+}
+__asm__(".symver strnvis_openbsd,strnvis@@LIBBSD_0.2");
+
 int
-strnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags)
+strnvis_netbsd(char *mbdst, size_t dlen, const char *mbsrc, int flags)
 {
        return istrsenvisxl(&mbdst, &dlen, mbsrc, flags, "", NULL);
 }
+__asm__(".symver strnvis_netbsd,strnvis@LIBBSD_0.9.1");
 
 int
 stravis(char **mbdstp, const char *mbsrc, int flags)
index 256574c618a5bb131ffee9d6b68abd748141ca5a..47063b9b5e12131b470ba626ad48c0783d0e231b 100644 (file)
@@ -19,3 +19,5 @@ setmode
 strl
 strmode
 strnstr
+vis
+vis-openbsd
index d86539a7142f129de9bf294d3f7e2897cab1a1bd..452558dca8c552b472e1478e22528a375c181c51 100644 (file)
@@ -47,6 +47,8 @@ check_PROGRAMS = \
        strl \
        strmode \
        strnstr \
+       vis \
+       vis-openbsd \
        $(nil)
 
 if HAVE_LIBTESTU01
diff --git a/test/vis-openbsd.c b/test/vis-openbsd.c
new file mode 100644 (file)
index 0000000..99c4198
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2018 Guillem Jover <guillem@hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <string.h>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcpp"
+#include <vis.h>
+#pragma GCC diagnostic pop
+
+int
+main(int argc, char **argv)
+{
+       char str[200];
+       char unstr[200];
+
+       strnvis(str, "0123456789abcdef", 10, 0);
+       assert(strcmp(str, "0123456789") == 0);
+
+       strnunvis(unstr, str, 100);
+       assert(strcmp(unstr, "0123456789") == 0);
+
+       return 0;
+}
diff --git a/test/vis.c b/test/vis.c
new file mode 100644 (file)
index 0000000..10b8b0f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2018 Guillem Jover <guillem@hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LIBBSD_NETBSD_VIS 1
+
+#include <assert.h>
+#include <string.h>
+#include <vis.h>
+
+int
+main(int argc, char **argv)
+{
+       char str[200];
+       char unstr[200];
+
+       strnvis(str, 10, "0123456789abcdef", 0);
+       assert(strcmp(str, "0123456789") == 0);
+
+       strnunvis(unstr, 100, str);
+       assert(strcmp(unstr, "0123456789") == 0);
+
+       return 0;
+}