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;
}
}
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_;
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));