};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(color_mode, ColorMode, COLOR_24BIT);
+
+/*
+ * Check that the string is formatted like an ANSI color code, i.e. that it consists of one or more
+ * sequences of ASCII digits separated by semicolons. This is equivalent to matching the regex:
+ * ^[0-9]+(;[0-9]+)*$
+ * This can be used to partially validate escape codes of the form "\x1B[%sm", accepting all valid
+ * ANSI color codes while rejecting anything that would result in garbled output (such as injecting
+ * text or changing the type of escape code).
+ */
+bool looks_like_ansi_color_code(const char *str) {
+ assert(str);
+
+ bool prev_char_was_digit = false;
+
+ for (char c = *str; c != '\0'; c = *(++str)) {
+ if (ascii_isdigit(c))
+ prev_char_was_digit = true;
+ else if (prev_char_was_digit && c == ';')
+ prev_char_was_digit = false;
+ else
+ return false;
+ }
+
+ return prev_char_was_digit;
+}
void reset_ansi_feature_caches(void);
+bool looks_like_ansi_color_code(const char *str);
+
/* Regular colors */
#define ANSI_BLACK "\x1B[0;30m" /* Some type of grey usually. */
#define ANSI_RED "\x1B[0;31m"
break;
case ARG_BACKGROUND:
- r = free_and_strdup_warn(&arg_background, optarg);
+ r = parse_background_argument(optarg, &arg_background);
if (r < 0)
return r;
break;
#include "fd-util.h"
#include "log.h"
#include "main-func.h"
+#include "parse-argument.h"
#include "pidref.h"
#include "pretty-print.h"
#include "process-util.h"
break;
case ARG_BACKGROUND:
- r = free_and_strdup_warn(&arg_background, optarg);
+ r = parse_background_argument(optarg, &arg_background);
if (r < 0)
return r;
break;
break;
case ARG_BACKGROUND:
- r = free_and_strdup_warn(&arg_background, optarg);
+ r = parse_background_argument(optarg, &arg_background);
if (r < 0)
return r;
break;
break;
case ARG_BACKGROUND:
- r = free_and_strdup_warn(&arg_background, optarg);
+ r = parse_background_argument(optarg, &arg_background);
if (r < 0)
return r;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
+#include "ansi-color.h"
#include "bus-util.h"
#include "format-table.h"
#include "hostname-util.h"
return 0;
}
+
+int parse_background_argument(const char *s, char **arg) {
+ if (!isempty(s) && !looks_like_ansi_color_code(s))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid --background= argument: %s", s);
+
+ return free_and_strdup_warn(arg, s);
+}
int parse_path_argument(const char *path, bool suppress_root, char **arg);
int parse_signal_argument(const char *s, int *ret);
int parse_machine_argument(const char *s, const char **ret_host, BusTransport *ret_transport);
+int parse_background_argument(const char *s, char **arg);
assert_se(signal == SIGABRT);
}
+TEST(parse_background_argument) {
+ _cleanup_free_ char *arg_bg_good = NULL;
+
+ /* Should accept empty string */
+ assert_se(parse_background_argument("", &arg_bg_good) >= 0);
+ ASSERT_STREQ(arg_bg_good, "");
+
+ /* Should accept ANSI color codes in palette, 8-bit, or 24-bit format */
+ assert_se(parse_background_argument("42", &arg_bg_good) >= 0);
+ ASSERT_STREQ(arg_bg_good, "42");
+
+ assert_se(parse_background_argument("48;5;219", &arg_bg_good) >= 0);
+ ASSERT_STREQ(arg_bg_good, "48;5;219");
+
+ assert_se(parse_background_argument("48;2;3;141;59", &arg_bg_good) >= 0);
+ ASSERT_STREQ(arg_bg_good, "48;2;3;141;59");
+
+ _cleanup_free_ char *arg_bg_bad = NULL;
+
+ /* Should reject various invalid arguments */
+ assert_se(parse_background_argument("42;", &arg_bg_bad) < 0);
+ ASSERT_NULL(arg_bg_bad);
+
+ assert_se(parse_background_argument(";42", &arg_bg_bad) < 0);
+ ASSERT_NULL(arg_bg_bad);
+
+ assert_se(parse_background_argument("4;;2", &arg_bg_bad) < 0);
+ ASSERT_NULL(arg_bg_bad);
+
+ assert_se(parse_background_argument("4a2", &arg_bg_bad) < 0);
+ ASSERT_NULL(arg_bg_bad);
+}
+
DEFINE_TEST_MAIN(LOG_INFO);
break;
case ARG_BACKGROUND:
- r = free_and_strdup_warn(&arg_background, optarg);
+ r = parse_background_argument(optarg, &arg_background);
if (r < 0)
return r;
break;