From: Luca Boccassi Date: Tue, 16 Jun 2026 20:55:33 +0000 (+0100) Subject: string-util: add STRING_DISALLOW_WHITESPACE for string_is_safe X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9404fa70df5afb747ee4610506a49ae4401069c4;p=thirdparty%2Fsystemd.git string-util: add STRING_DISALLOW_WHITESPACE for string_is_safe Co-developed-by: Claude Opus 4.8 --- diff --git a/src/basic/string-util.c b/src/basic/string-util.c index b972f7a42c9..cfeb2e3917a 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -1129,6 +1129,9 @@ bool string_is_safe(const char *p, StringSafeFlags flags) { if (!FLAGS_SET(flags, STRING_ALLOW_GLOBS) && strchr(GLOB_CHARS, *t)) return false; + if (FLAGS_SET(flags, STRING_DISALLOW_WHITESPACE) && strchr(WHITESPACE, *t)) + return false; + if (FLAGS_SET(flags, STRING_ASCII) && (uint8_t) *t >= 0x80) return false; } diff --git a/src/basic/string-util.h b/src/basic/string-util.h index 447f4f807e7..6242f559312 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -222,13 +222,14 @@ static inline int strdup_to(char **ret, const char *src) { } typedef enum StringSafeFlags { - STRING_ASCII = 1 << 0, /* Verify string is 7-Bit ASCII (rather than just UTF-8) */ - STRING_ALLOW_EMPTY = 1 << 1, /* Allow empty strings */ - STRING_ALLOW_NEWLINES = 1 << 2, /* Allow newlines (\n) */ - STRING_ALLOW_BACKSLASHES = 1 << 3, /* Allow backslashes (\) */ - STRING_ALLOW_QUOTES = 1 << 4, /* Allow quotes (" or ') */ - STRING_ALLOW_GLOBS = 1 << 5, /* Allow globs (?, * or [) */ - STRING_FILENAME = 1 << 6, /* Verify the string is valid as regular filename */ + STRING_ASCII = 1 << 0, /* Verify string is 7-Bit ASCII (rather than just UTF-8) */ + STRING_ALLOW_EMPTY = 1 << 1, /* Allow empty strings */ + STRING_ALLOW_NEWLINES = 1 << 2, /* Allow newlines (\n) */ + STRING_ALLOW_BACKSLASHES = 1 << 3, /* Allow backslashes (\) */ + STRING_ALLOW_QUOTES = 1 << 4, /* Allow quotes (" or ') */ + STRING_ALLOW_GLOBS = 1 << 5, /* Allow globs (?, * or [) */ + STRING_FILENAME = 1 << 6, /* Verify the string is valid as regular filename */ + STRING_DISALLOW_WHITESPACE = 1 << 7, /* Refuse whitespace (space, tab, newline, …) */ } StringSafeFlags; bool string_is_safe(const char *p, StringSafeFlags flags) _pure_; diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c index 4a8656f4110..648b8fa839d 100644 --- a/src/test/test-string-util.c +++ b/src/test/test-string-util.c @@ -1607,6 +1607,21 @@ TEST(string_is_safe) { ASSERT_FALSE(string_is_safe("/foo", STRING_FILENAME)); ASSERT_FALSE(string_is_safe("foo/bar", STRING_FILENAME)); + /* STRING_DISALLOW_WHITESPACE: rejects whitespace (space, tab, newline, carriage return). */ + ASSERT_TRUE(string_is_safe("hello", STRING_DISALLOW_WHITESPACE)); + ASSERT_TRUE(string_is_safe("foo-bar_baz", STRING_DISALLOW_WHITESPACE)); + ASSERT_TRUE(string_is_safe("über", STRING_DISALLOW_WHITESPACE)); /* valid UTF-8 still allowed */ + ASSERT_TRUE(string_is_safe("hello world", 0)); /* space accepted by default */ + ASSERT_FALSE(string_is_safe("hello world", STRING_DISALLOW_WHITESPACE)); /* but not with the flag */ + ASSERT_FALSE(string_is_safe(" ", STRING_DISALLOW_WHITESPACE)); + ASSERT_FALSE(string_is_safe("foo ", STRING_DISALLOW_WHITESPACE)); + ASSERT_FALSE(string_is_safe(" foo", STRING_DISALLOW_WHITESPACE)); + ASSERT_FALSE(string_is_safe("a\tb", STRING_DISALLOW_WHITESPACE)); + ASSERT_FALSE(string_is_safe("a\rb", STRING_DISALLOW_WHITESPACE)); + /* The flag overrides STRING_ALLOW_NEWLINES for the newline character, which is whitespace too. */ + ASSERT_TRUE(string_is_safe("a\nb", STRING_ALLOW_NEWLINES)); + ASSERT_FALSE(string_is_safe("a\nb", STRING_ALLOW_NEWLINES | STRING_DISALLOW_WHITESPACE)); + /* Pairwise combinations. */ ASSERT_TRUE(string_is_safe("", STRING_ALLOW_EMPTY | STRING_ASCII)); ASSERT_FALSE(string_is_safe("über", STRING_ALLOW_EMPTY | STRING_ASCII));