commit 32e1bb04f13ad9e19df9eb34cd86380ae56e51ae
parent 5666f7a3efab6a04b328c0d7356b00b6b2194e53
Author: Christian Grothoff <christian@grothoff.org>
Date: Thu, 29 Oct 2026 19:46:24 +0100
avoid isalnum() to prevent locale-dependence
Diffstat:
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/src/util/test_slug.c b/src/util/test_slug.c
@@ -50,6 +50,11 @@ check_slug (void)
{"a#b", false},
{"a&b", false},
{"a@b", false},
+ /* Bytes >= 0x80 are rejected whatever the locale says about them:
+ "\u00e4" in UTF-8, and the same two bytes are each a letter in
+ ISO-8859-1. */
+ {"a\xc3\xa4b", false},
+ {"\xe4", false},
};
unsigned int failed = 0;
@@ -98,6 +103,8 @@ check_session_id (void)
{"a#b", false},
{"a&b", false},
{"a@b", false},
+ {"a\xc3\xa4b", false},
+ {"\xe4", false},
};
unsigned int failed = 0;
diff --git a/src/util/util.c b/src/util/util.c
@@ -474,6 +474,27 @@ TALER_words_destroy (char **args)
}
+/**
+ * Is @a c an ASCII letter or digit?
+ *
+ * Deliberately not isalnum(): that function is locale-dependent, and
+ * GNUNET_PROGRAM_run() calls setlocale(LC_ALL, "") when NLS is enabled.
+ * Under a single-byte non-ASCII locale (ISO-8859-x) isalnum() accepts
+ * bytes >= 0x80, which would make the slug and session ID character sets
+ * depend on the environment the service happens to run in.
+ *
+ * @param c character to test
+ * @return true if @a c is in [A-Za-z0-9]
+ */
+static bool
+is_ascii_alnum (unsigned char c)
+{
+ return ( ( ('a' <= c) && ('z' >= c) ) ||
+ ( ('A' <= c) && ('Z' >= c) ) ||
+ ( ('0' <= c) && ('9' >= c) ) );
+}
+
+
bool
TALER_is_slug (const char *slug)
{
@@ -491,7 +512,7 @@ TALER_is_slug (const char *slug)
{
unsigned char c = *p;
- if (isalnum (c))
+ if (is_ascii_alnum (c))
continue;
switch (c)
@@ -534,7 +555,7 @@ TALER_is_session_id (const char *session_id)
{
unsigned char c = *p;
- if (isalnum (c))
+ if (is_ascii_alnum (c))
continue;
switch (c)