Blob Blame History Raw
From 477b7b679d58455dc38c2594b29a1ecfbe88e80c Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 2 Nov 2020 14:55:27 -0500
Subject: [PATCH 1/2] Fix: libcrmcommon: Prevent a segfault in
 pcmk__cmdline_preproc.

The list of special single-character args is optional.  The function
currently handles it being an empty string, but it should handle a NULL
as well.
---
 lib/common/cmdline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/common/cmdline.c b/lib/common/cmdline.c
index d66ccc7..66f1976 100644
--- a/lib/common/cmdline.c
+++ b/lib/common/cmdline.c
@@ -203,7 +203,7 @@ pcmk__cmdline_preproc(char **argv, const char *special) {
                  * glib does not.  Grab both the argument and its value and
                  * separate them into a new argument.
                  */
-                if (strchr(special, *ch) != NULL) {
+                if (special != NULL && strchr(special, *ch) != NULL) {
                     /* The argument does not occur at the end of this string of
                      * arguments.  Take everything through the end as its value.
                      */
-- 
1.8.3.1


From d1f4a975fa783045254521f415f1899b34ee96e3 Mon Sep 17 00:00:00 2001
From: Chris Lumens <clumens@redhat.com>
Date: Mon, 2 Nov 2020 16:06:29 -0500
Subject: [PATCH 2/2] Test: libcrmcommon: Add unit tests for
 pcmk__cmdline_preproc.

---
 configure.ac                                       |   1 +
 lib/common/tests/Makefile.am                       |   2 +-
 lib/common/tests/cmdline/Makefile.am               |  29 ++++++
 .../tests/cmdline/pcmk__cmdline_preproc_test.c     | 102 +++++++++++++++++++++
 4 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 lib/common/tests/cmdline/Makefile.am
 create mode 100644 lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c

diff --git a/configure.ac b/configure.ac
index 7ed4a30..36e85a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2006,6 +2006,7 @@ AC_CONFIG_FILES(Makefile                                            \
                 lib/pacemaker-cluster.pc                            \
                 lib/common/Makefile                                 \
                 lib/common/tests/Makefile                           \
+                lib/common/tests/cmdline/Makefile                   \
                 lib/common/tests/flags/Makefile                     \
                 lib/common/tests/operations/Makefile                \
                 lib/common/tests/strings/Makefile                   \
diff --git a/lib/common/tests/Makefile.am b/lib/common/tests/Makefile.am
index 33c45cb..f3eaeec 100644
--- a/lib/common/tests/Makefile.am
+++ b/lib/common/tests/Makefile.am
@@ -1 +1 @@
-SUBDIRS = flags operations strings utils
+SUBDIRS = cmdline flags operations strings utils
diff --git a/lib/common/tests/cmdline/Makefile.am b/lib/common/tests/cmdline/Makefile.am
new file mode 100644
index 0000000..e69ef21
--- /dev/null
+++ b/lib/common/tests/cmdline/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright 2020 the Pacemaker project contributors
+#
+# The version control history for this file may have further details.
+#
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
+#
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
+LDADD = $(top_builddir)/lib/common/libcrmcommon.la
+
+include $(top_srcdir)/mk/glib-tap.mk
+
+# Add each test program here.  Each test should be written as a little standalone
+# program using the glib unit testing functions.  See the documentation for more
+# information.
+#
+# https://developer.gnome.org/glib/unstable/glib-Testing.html
+#
+# Add "_test" to the end of all test program names to simplify .gitignore.
+test_programs = pcmk__cmdline_preproc_test
+
+# If any extra data needs to be added to the source distribution, add it to the
+# following list.
+dist_test_data =
+
+# If any extra data needs to be used by tests but should not be added to the
+# source distribution, add it to the following list.
+test_data =
diff --git a/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c
new file mode 100644
index 0000000..e13c983
--- /dev/null
+++ b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2020 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU Lesser General Public License
+ * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+#include <crm/common/cmdline_internal.h>
+
+#define LISTS_EQ(a, b) { \
+    g_assert_cmpint(g_strv_length((gchar **) (a)), ==, g_strv_length((gchar **) (b))); \
+    for (int i = 0; i < g_strv_length((a)); i++) { \
+        g_assert_cmpstr((a)[i], ==, (b)[i]); \
+    } \
+}
+
+static void
+empty_input(void) {
+    g_assert_cmpint(pcmk__cmdline_preproc(NULL, "") == NULL, ==, TRUE);
+}
+
+static void
+no_specials(void) {
+    const char *argv[] = { "-a", "-b", "-c", "-d", NULL };
+    const gchar *expected[] = { "-a", "-b", "-c", "-d", NULL };
+
+    gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL);
+    LISTS_EQ(processed, expected);
+    g_strfreev(processed);
+
+    processed = pcmk__cmdline_preproc((char **) argv, "");
+    LISTS_EQ(processed, expected);
+    g_strfreev(processed);
+}
+
+static void
+single_dash(void) {
+    const char *argv[] = { "-", NULL };
+    const gchar *expected[] = { "-", NULL };
+
+    gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL);
+    LISTS_EQ(processed, expected);
+    g_strfreev(processed);
+}
+
+static void
+double_dash(void) {
+    const char *argv[] = { "-a", "--", "-bc", NULL };
+    const gchar *expected[] = { "-a", "--", "-bc", NULL };
+
+    gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL);
+    LISTS_EQ(processed, expected);
+    g_strfreev(processed);
+}
+
+static void
+special_args(void) {
+    const char *argv[] = { "-aX", "-Fval", NULL };
+    const gchar *expected[] = { "-a", "X", "-F", "val", NULL };
+
+    gchar **processed = pcmk__cmdline_preproc((char **) argv, "aF");
+    LISTS_EQ(processed, expected);
+    g_strfreev(processed);
+}
+
+static void
+special_arg_at_end(void) {
+    const char *argv[] = { "-a", NULL };
+    const gchar *expected[] = { "-a", NULL };
+
+    gchar **processed = pcmk__cmdline_preproc((char **) argv, "a");
+    LISTS_EQ(processed, expected);
+    g_strfreev(processed);
+}
+
+static void
+long_arg(void) {
+    const char *argv[] = { "--blah=foo", NULL };
+    const gchar *expected[] = { "--blah=foo", NULL };
+
+    gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL);
+    LISTS_EQ(processed, expected);
+    g_strfreev(processed);
+}
+
+int
+main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/common/cmdline/preproc/empty_input", empty_input);
+    g_test_add_func("/common/cmdline/preproc/no_specials", no_specials);
+    g_test_add_func("/common/cmdline/preproc/single_dash", single_dash);
+    g_test_add_func("/common/cmdline/preproc/double_dash", double_dash);
+    g_test_add_func("/common/cmdline/preproc/special_args", special_args);
+    g_test_add_func("/common/cmdline/preproc/special_arg_at_end", special_arg_at_end);
+    g_test_add_func("/common/cmdline/preproc/long_arg", long_arg);
+    return g_test_run();
+}
-- 
1.8.3.1