summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2013-03-19 14:50:32 +0100
committerStef Walter <stefw@gnome.org>2013-03-19 16:47:05 +0100
commit7c27e9fbbe86b3268065f248eab2d6964983a715 (patch)
tree72127883de5d9c97c7432a7fc651d9259caf38fe /common
parent535475c238c427cb685b4282997f7bce0876bfdf (diff)
trust: Don't use POSIX or GNU basename()
Both are nasty. Do our own, and test it a bit https://bugs.freedesktop.org/show_bug.cgi?id=62479
Diffstat (limited to 'common')
-rw-r--r--common/compat.c44
-rw-r--r--common/compat.h17
-rw-r--r--common/tests/Makefile.am1
-rw-r--r--common/tests/test-compat.c93
4 files changed, 131 insertions, 24 deletions
diff --git a/common/compat.c b/common/compat.c
index 4e99d11..2548459 100644
--- a/common/compat.c
+++ b/common/compat.c
@@ -148,31 +148,39 @@ getprogname (void)
#endif /* HAVE_GETPROGNAME */
-#ifndef HAVE_BASENAME
-
char *
-basename (const char *name)
+p11_basename (const char *name)
{
- char *p;
#ifdef OS_WIN32
- char *p2;
+ static const char *delims = "/\\";
+#else
+ static const char *delims = "/";
#endif
- if (!name || name[0] == '\0')
- return ".";
+ const char *end;
+ const char *beg;
- p = strrchr (name, '/');
-#ifdef OS_WIN32
- p2 = strrchr (name, '\\');
- if (p2 > p)
- p = p2;
-#endif
- if (p != NULL)
- return p + 1;
- return (char *)name;
-}
+ if (name == NULL)
+ return NULL;
+
+ /* Any trailing slashes */
+ end = name + strlen (name);
+ while (end != name) {
+ if (!strchr (delims, *(end - 1)))
+ break;
+ end--;
+ }
-#endif /* HAVE_BASENAME */
+ /* Find the last slash after those */
+ beg = end;
+ while (beg != name) {
+ if (strchr (delims, *(beg - 1)))
+ break;
+ beg--;
+ }
+
+ return strndup (beg, end - beg);
+}
#ifdef OS_UNIX
#include <sys/stat.h>
diff --git a/common/compat.h b/common/compat.h
index a6a02af..bd933cb 100644
--- a/common/compat.h
+++ b/common/compat.h
@@ -72,12 +72,6 @@
const char * getprogname (void);
#endif
-#ifndef HAVE_BASENAME
-
-char * basename (const char *name);
-
-#endif /* HAVE_BASENAME */
-
#ifndef HAVE_MKSTEMP
int mkstemp (char *template);
@@ -220,6 +214,17 @@ void p11_mmap_close (p11_mmap *map);
#endif /* OS_UNIX */
+/*
+ * The semantics of both POSIX basename() and GNU asename() are so crappy that
+ * we just don't even bother. And what's worse is how it completely changes
+ * behavior if _GNU_SOURCE is defined. Nasty stuff.
+ */
+char * p11_basename (const char *name);
+
+/* ----------------------------------------------------------------------------
+ * MORE COMPAT
+ */
+
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif /* HAVE_ERRNO_H */
diff --git a/common/tests/Makefile.am b/common/tests/Makefile.am
index e14fddd..85893cb 100644
--- a/common/tests/Makefile.am
+++ b/common/tests/Makefile.am
@@ -15,6 +15,7 @@ LDADD = \
$(NULL)
CHECK_PROGS = \
+ test-compat \
test-dict \
test-array \
test-constants \
diff --git a/common/tests/test-compat.c b/common/tests/test-compat.c
new file mode 100644
index 0000000..13a7a33
--- /dev/null
+++ b/common/tests/test-compat.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * 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.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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
+ * COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "compat.h"
+
+static void
+test_basename (CuTest *tc)
+{
+ struct {
+ const char *in;
+ const char *out;
+ } fixtures[] = {
+ { "/this/is/a/path", "path" },
+ { "/this/is/a/folder/", "folder" },
+ { "folder/", "folder" },
+ { "/", "" },
+ { "this", "this" },
+#ifdef OS_WIN32
+ { "\\this\\is\\a\\path", "path" },
+ { "\\this\\is\\a\\folder\\", "folder" },
+ { "folder\\", "folder" },
+ { "\\", "" },
+#endif
+ { NULL },
+ };
+
+ char *out;
+ int i;
+
+ for (i = 0; fixtures[i].in != NULL; i++) {
+ out = p11_basename (fixtures[i].in);
+ CuAssertStrEquals (tc, fixtures[i].out, out);
+ free (out);
+ }
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ SUITE_ADD_TEST (suite, test_basename);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}