From ea5510dd979bb6d375324cda26925d9e7c4362f5 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Mon, 19 Jul 2021 10:04:16 -0400 Subject: [PATCH 1/2] Low: tools: The --get-value option does not require an arg. Regression in 2.1.0 introduced by 15f5c2901. --- tools/crm_attribute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/crm_attribute.c b/tools/crm_attribute.c index 2cc8d26..8a5b4e4 100644 --- a/tools/crm_attribute.c +++ b/tools/crm_attribute.c @@ -242,7 +242,7 @@ static GOptionEntry deprecated_entries[] = { NULL, NULL }, - { "get-value", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, value_cb, + { "get-value", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, value_cb, NULL, NULL }, -- 1.8.3.1 From ef054d943afe8e60017f6adc4e25f88a59ac91a4 Mon Sep 17 00:00:00 2001 From: Chris Lumens Date: Mon, 19 Jul 2021 11:37:04 -0400 Subject: [PATCH 2/2] Low: libcrmcommon: Allow negative numbers as cmdline options. The bug here is that negative numbers (for instance, negative scores) are not supported as command line arguments. Because we break up a string that starts with a single dash into multiple arguments, "-1000" becomes "-1", "-0", "-0", and "-0". Because we don't have enough information about what is happening on the command line, the best we can do here is recognize something as a negative number and pass it on. Any errors will have to be detected at a later step. Also note that we only recognize negative numbers if they start with 1-9. Starting with 0 will be recognized as some sort of string. Regression in 2.1.0 caused by a long-standing bug in pcmk__cmdline_preproc_test. --- lib/common/cmdline.c | 29 ++++++++++++++++++++++ .../tests/cmdline/pcmk__cmdline_preproc_test.c | 24 +++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/common/cmdline.c b/lib/common/cmdline.c index 7c95d02..9c1b810 100644 --- a/lib/common/cmdline.c +++ b/lib/common/cmdline.c @@ -9,6 +9,7 @@ #include +#include #include #include @@ -189,6 +190,34 @@ pcmk__cmdline_preproc(char **argv, const char *special) { /* Skip over leading dash */ char *ch = argv[i]+1; + /* This looks like the start of a number, which means it is a negative + * number. It's probably the argument to the preceeding option, but + * we can't know that here. Copy it over and let whatever handles + * arguments next figure it out. + */ + if (*ch != '\0' && *ch >= '1' && *ch <= '9') { + bool is_numeric = true; + + while (*ch != '\0') { + if (!isdigit(*ch)) { + is_numeric = false; + break; + } + + ch++; + } + + if (is_numeric) { + g_ptr_array_add(arr, g_strdup_printf("%s", argv[i])); + continue; + } else { + /* This argument wasn't entirely numeric. Reset ch to the + * beginning so we can process it one character at a time. + */ + ch = argv[i]+1; + } + } + while (*ch != '\0') { /* This is a special short argument that takes an option. getopt * allows values to be interspersed with a list of arguments, but diff --git a/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c index b8506c6..9a752ef 100644 --- a/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c +++ b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 the Pacemaker project contributors + * Copyright 2020-2021 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -86,6 +86,26 @@ long_arg(void) { g_strfreev(processed); } +static void +negative_score(void) { + const char *argv[] = { "-v", "-1000", NULL }; + const gchar *expected[] = { "-v", "-1000", NULL }; + + gchar **processed = pcmk__cmdline_preproc((char **) argv, "v"); + LISTS_EQ(processed, expected); + g_strfreev(processed); +} + +static void +negative_score_2(void) { + const char *argv[] = { "-1i3", NULL }; + const gchar *expected[] = { "-1", "-i", "-3", NULL }; + + gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); + LISTS_EQ(processed, expected); + g_strfreev(processed); +} + int main(int argc, char **argv) { @@ -98,5 +118,7 @@ main(int argc, char **argv) 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); + g_test_add_func("/common/cmdline/preproc/negative_score", negative_score); + g_test_add_func("/common/cmdline/preproc/negative_score_2", negative_score_2); return g_test_run(); } -- 1.8.3.1