From 45b4ff7662bb542fc4de4453a9ac476f81bbe46d Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 2 Jan 2026 21:15:24 +0100 Subject: [PATCH 01/14] lib/string/ctype/isascii.[ch]: is*_c(): Add APIs These are like the isascii(3) family of APIs, but use the C locale, as the _c suffix hints. These macros behave well with non-casted input, unlike isascii(3). The isascii_c() and iscntrl_c() implementations are different from the rest because they must return true for '\0'. Reported-by: Tobias Stoeckmann Cc: Paul Eggert Signed-off-by: Alejandro Colomar --- lib/Makefile.am | 2 ++ lib/string/README | 6 +++++ lib/string/ctype/isascii.c | 7 ++++++ lib/string/ctype/isascii.h | 49 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 lib/string/ctype/isascii.c create mode 100644 lib/string/ctype/isascii.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 7c488f8266..60c73ec388 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -191,6 +191,8 @@ libshadow_la_SOURCES = \ spawn.c \ sssd.c \ sssd.h \ + string/ctype/isascii.c \ + string/ctype/isascii.h \ string/ctype/strchrisascii/strchriscntrl.c \ string/ctype/strchrisascii/strchriscntrl.h \ string/ctype/strisascii/strisdigit.c \ diff --git a/lib/string/README b/lib/string/README index b8a231b408..6c1094cd4a 100644 --- a/lib/string/README +++ b/lib/string/README @@ -69,6 +69,12 @@ Specific guidelines: ctype/ - Character classification and conversion functions + isascii.h + The functions defined in this file + return true + if the character + belongs to the category specified in the function name. + strchrisascii/ The functions defined under this directory return true diff --git a/lib/string/ctype/isascii.c b/lib/string/ctype/isascii.c new file mode 100644 index 0000000000..5409883124 --- /dev/null +++ b/lib/string/ctype/isascii.c @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar +// SPDX-License-Identifier: BSD-3-Clause + + +#include "config.h" + +#include "string/ctype/isascii.h" diff --git a/lib/string/ctype/isascii.h b/lib/string/ctype/isascii.h new file mode 100644 index 0000000000..8a1b47fcff --- /dev/null +++ b/lib/string/ctype/isascii.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar +// SPDX-License-Identifier: BSD-3-Clause + + +#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_ISASCII_H_ +#define SHADOW_INCLUDE_LIB_STRING_CTYPE_ISASCII_H_ + + +#include "config.h" + +#include + +#include "string/strcmp/streq.h" + + +#define CTYPE_CNTRL_C \ + "\x7F" \ + "\x1F\x1E\x1D\x1C\x1B\x1A\x19\x18\x17\x16\x15\x14\x13\x12\x11\x10" \ + "\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07\x06\x05\x04\x03\x02\x01" /*NUL*/ + +#define CTYPE_LOWER_C "abcdefghijklmnopqrstuvwxyz" +#define CTYPE_UPPER_C "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define CTYPE_DIGIT_C "0123456789" +#define CTYPE_PUNCT_C "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" +#define CTYPE_SPACE_C " \t\n\v\f\r" +#define CTYPE_ALPHA_C CTYPE_LOWER_C CTYPE_UPPER_C +#define CTYPE_ALNUM_C CTYPE_ALPHA_C CTYPE_DIGIT_C +#define CTYPE_GRAPH_C CTYPE_ALNUM_C CTYPE_PUNCT_C +#define CTYPE_PRINT_C CTYPE_GRAPH_C " " +#define CTYPE_XDIGIT_C CTYPE_DIGIT_C "abcdefABCDEF" +#define CTYPE_ASCII_C CTYPE_PRINT_C CTYPE_CNTRL_C /*NUL*/ + + +// isascii_c - is [:ascii:] C-locale +#define isascii_c(c) (!!strchr(CTYPE_ASCII_C, c)) +#define iscntrl_c(c) (!!strchr(CTYPE_CNTRL_C, c)) +#define islower_c(c) (!streq(strchrnul(CTYPE_LOWER_C, c), "")) +#define isupper_c(c) (!streq(strchrnul(CTYPE_UPPER_C, c), "")) +#define isdigit_c(c) (!streq(strchrnul(CTYPE_DIGIT_C, c), "")) +#define ispunct_c(c) (!streq(strchrnul(CTYPE_PUNCT_C, c), "")) +#define isspace_c(c) (!streq(strchrnul(CTYPE_SPACE_C, c), "")) +#define isalpha_c(c) (!streq(strchrnul(CTYPE_ALPHA_C, c), "")) +#define isalnum_c(c) (!streq(strchrnul(CTYPE_ALNUM_C, c), "")) +#define isgraph_c(c) (!streq(strchrnul(CTYPE_GRAPH_C, c), "")) +#define isprint_c(c) (!streq(strchrnul(CTYPE_PRINT_C, c), "")) +#define isxdigit_c(c) (!streq(strchrnul(CTYPE_XDIGIT_C, c), "")) + + +#endif // include guard From c8a29c6121a9039bb3a2d44979b30d1c6e497cce Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 2 Jan 2026 21:29:27 +0100 Subject: [PATCH 02/14] lib/, src/: Use isascii_c() functions instead of isascii(3) We want to use the C locale. Reported-by: Tobias Stoeckmann Signed-off-by: Alejandro Colomar --- lib/getrange.c | 3 ++- lib/port.c | 7 ++++--- lib/string/ctype/strchrisascii/strchriscntrl.h | 7 +++---- lib/string/ctype/strisascii/strisdigit.h | 6 +++--- lib/string/ctype/strisascii/strisprint.h | 9 +++------ src/newusers.c | 7 ++++--- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/lib/getrange.c b/lib/getrange.c index a7f8f05963..a7dd844f67 100644 --- a/lib/getrange.c +++ b/lib/getrange.c @@ -13,6 +13,7 @@ #include "atoi/a2i.h" #include "defines.h" #include "prototypes.h" +#include "string/ctype/isascii.h" #include "string/strcmp/streq.h" @@ -57,7 +58,7 @@ getrange(const char *range, if (streq(end, "")) return 0; /* - */ parse_max: - if (!isdigit((unsigned char) *end)) + if (!isdigit_c(*end)) return -1; if (a2ul(max, end, NULL, 10, *min, ULONG_MAX) == -1) diff --git a/lib/port.c b/lib/port.c index 8cf6f39fb9..cde50b27e2 100644 --- a/lib/port.c +++ b/lib/port.c @@ -20,6 +20,7 @@ #include "io/fgets/fgets.h" #include "port.h" #include "prototypes.h" +#include "string/ctype/isascii.h" #include "string/strcmp/streq.h" #include "string/strcmp/strprefix.h" #include "string/strtok/stpsep.h" @@ -212,7 +213,7 @@ getportent(void) * week or the other two values. */ - for (i = 0; isalpha(cp[i]) && ('\0' != cp[i + 1]); i += 2) { + for (i = 0; isalpha_c(cp[i]) && ('\0' != cp[i + 1]); i += 2) { switch ((cp[i] << 8) | (cp[i + 1])) { case ('S' << 8) | 'u': port.pt_times[j].t_days |= 01; @@ -261,7 +262,7 @@ getportent(void) * representing the times of day. */ - for (dtime = 0; isdigit (cp[i]); i++) { + for (dtime = 0; isdigit_c(cp[i]); i++) { dtime = dtime * 10 + cp[i] - '0'; } @@ -271,7 +272,7 @@ getportent(void) port.pt_times[j].t_start = dtime; cp = cp + i + 1; - for (dtime = 0, i = 0; isdigit (cp[i]); i++) { + for (dtime = 0, i = 0; isdigit_c(cp[i]); i++) { dtime = dtime * 10 + cp[i] - '0'; } diff --git a/lib/string/ctype/strchrisascii/strchriscntrl.h b/lib/string/ctype/strchrisascii/strchriscntrl.h index a1eaca371e..8fe6e05752 100644 --- a/lib/string/ctype/strchrisascii/strchriscntrl.h +++ b/lib/string/ctype/strchrisascii/strchriscntrl.h @@ -8,24 +8,23 @@ #include "config.h" -#include #include +#include "string/ctype/isascii.h" #include "string/strcmp/streq.h" inline bool strchriscntrl(const char *s); -// string character is [:cntrl:] -// Return true if any iscntrl(3) character is found in the string. +// strchriscntrl - string character is [:cntrl:] inline bool strchriscntrl(const char *s) { for (; !streq(s, ""); s++) { unsigned char c = *s; - if (iscntrl(c)) + if (iscntrl_c(c)) return true; } diff --git a/lib/string/ctype/strisascii/strisdigit.h b/lib/string/ctype/strisascii/strisdigit.h index 0c5175fc8d..1e4f69d2cd 100644 --- a/lib/string/ctype/strisascii/strisdigit.h +++ b/lib/string/ctype/strisascii/strisdigit.h @@ -10,6 +10,7 @@ #include +#include "string/ctype/isascii.h" #include "string/strcmp/streq.h" #include "string/strspn/stpspn.h" @@ -17,15 +18,14 @@ inline bool strisdigit(const char *s); -// string is [:digit:] -// Like isdigit(3), but check all characters in the string. +// strisdigit - string is [:digit:] inline bool strisdigit(const char *s) { if (streq(s, "")) return false; - return streq(stpspn(s, "0123456789"), ""); + return streq(stpspn(s, CTYPE_DIGIT_C), ""); } diff --git a/lib/string/ctype/strisascii/strisprint.h b/lib/string/ctype/strisascii/strisprint.h index 566dbf886d..652c6544d3 100644 --- a/lib/string/ctype/strisascii/strisprint.h +++ b/lib/string/ctype/strisascii/strisprint.h @@ -8,17 +8,16 @@ #include "config.h" -#include #include +#include "string/ctype/isascii.h" #include "string/strcmp/streq.h" inline bool strisprint(const char *s); -// string is [:print:] -// Like isprint(3), but check all characters in the string. +// strisprint - string is [:print:] inline bool strisprint(const char *s) { @@ -26,9 +25,7 @@ strisprint(const char *s) return false; for (; !streq(s, ""); s++) { - unsigned char c = *s; - - if (!isprint(c)) + if (!isprint_c(*s)) return false; } diff --git a/src/newusers.c b/src/newusers.c index 25f0841eba..1cf0bc9707 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -52,6 +52,7 @@ #include "shadow/gshadow/sgrp.h" #include "shadowlog.h" #include "sssd.h" +#include "string/ctype/isascii.h" #include "string/sprintf/snprintf.h" #include "string/strcmp/streq.h" #include "string/strdup/strdup.h" @@ -235,7 +236,7 @@ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid) return 0; } - if (isdigit (gid[0])) { + if (isdigit_c(gid[0])) { /* * The GID is a number, which means either this is a brand * new group, or an existing group. @@ -279,7 +280,7 @@ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid) /* * Now I have all of the fields required to create the new group. */ - if (!streq(gid, "") && (!isdigit(gid[0]))) { + if (!streq(gid, "") && (!isdigit_c(gid[0]))) { grent.gr_name = xstrdup (gid); } else { grent.gr_name = xstrdup (name); @@ -344,7 +345,7 @@ static int get_user_id (const char *uid, uid_t *nuid) { * The first guess for the UID is either the numerical UID that the * caller provided, or the next available UID. */ - if (isdigit (uid[0])) { + if (isdigit_c(uid[0])) { if ((get_uid(uid, nuid) == -1) || (*nuid == (uid_t)-1)) { fprintf (stderr, _("%s: invalid user ID '%s'\n"), From 4a129a8968dd435b858d02255f21e43e32b97a33 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 2 Jan 2026 13:57:19 +0100 Subject: [PATCH 03/14] lib/: Merge directories "lib/string/ctype/*" into unified files The APIs defined under each of those subdirs are too similar and related that it makes more sense to define them in the same files. (BTW, we only had one API per subdir, except in one subdir that had two APIs, so in the end, we have almost the same separation.) Signed-off-by: Alejandro Colomar --- lib/Makefile.am | 14 ++++---- lib/chkname.c | 4 +-- lib/fields.c | 4 +-- lib/obscure.c | 2 +- lib/string/README | 12 +++---- .../strchriscntrl.c => strchrisascii.c} | 2 +- .../strchriscntrl.h => strchrisascii.h} | 4 +-- .../{strisascii/strisprint.c => strisascii.c} | 3 +- .../{strisascii/strisdigit.h => strisascii.h} | 21 +++++++++-- lib/string/ctype/strisascii/strisdigit.c | 12 ------- lib/string/ctype/strisascii/strisprint.h | 36 ------------------- .../{strtoascii/strtolower.c => strtoascii.c} | 2 +- .../{strtoascii/strtolower.h => strtoascii.h} | 8 ++--- lib/subordinateio.c | 2 +- 14 files changed, 46 insertions(+), 80 deletions(-) rename lib/string/ctype/{strchrisascii/strchriscntrl.c => strchrisascii.c} (79%) rename lib/string/ctype/{strchrisascii/strchriscntrl.h => strchrisascii.h} (78%) rename lib/string/ctype/{strisascii/strisprint.c => strisascii.c} (70%) rename lib/string/ctype/{strisascii/strisdigit.h => strisascii.h} (58%) delete mode 100644 lib/string/ctype/strisascii/strisdigit.c delete mode 100644 lib/string/ctype/strisascii/strisprint.h rename lib/string/ctype/{strtoascii/strtolower.c => strtoascii.c} (78%) rename lib/string/ctype/{strtoascii/strtolower.h => strtoascii.h} (61%) diff --git a/lib/Makefile.am b/lib/Makefile.am index 60c73ec388..a6c41abe4b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -193,14 +193,12 @@ libshadow_la_SOURCES = \ sssd.h \ string/ctype/isascii.c \ string/ctype/isascii.h \ - string/ctype/strchrisascii/strchriscntrl.c \ - string/ctype/strchrisascii/strchriscntrl.h \ - string/ctype/strisascii/strisdigit.c \ - string/ctype/strisascii/strisdigit.h \ - string/ctype/strisascii/strisprint.c \ - string/ctype/strisascii/strisprint.h \ - string/ctype/strtoascii/strtolower.c \ - string/ctype/strtoascii/strtolower.h \ + string/ctype/strchrisascii.c \ + string/ctype/strchrisascii.h \ + string/ctype/strisascii.c \ + string/ctype/strisascii.h \ + string/ctype/strtoascii.c \ + string/ctype/strtoascii.h \ string/memset/memzero.c \ string/memset/memzero.h \ string/sprintf/aprintf.c \ diff --git a/lib/chkname.c b/lib/chkname.c index 0b6d9409cc..18708defb8 100644 --- a/lib/chkname.c +++ b/lib/chkname.c @@ -33,8 +33,8 @@ #include "defines.h" #include "chkname.h" -#include "string/ctype/strchrisascii/strchriscntrl.h" -#include "string/ctype/strisascii/strisdigit.h" +#include "string/ctype/strchrisascii.h" +#include "string/ctype/strisascii.h" #include "string/strcmp/streq.h" #include "string/strcmp/strcaseeq.h" #include "sysconf.h" diff --git a/lib/fields.c b/lib/fields.c index 759dea755f..77eb8c2d4f 100644 --- a/lib/fields.c +++ b/lib/fields.c @@ -19,8 +19,8 @@ #include "io/fgets/fgets.h" #include "prototypes.h" -#include "string/ctype/strisascii/strisprint.h" -#include "string/ctype/strchrisascii/strchriscntrl.h" +#include "string/ctype/strisascii.h" +#include "string/ctype/strchrisascii.h" #include "string/strcmp/streq.h" #include "string/strspn/stpspn.h" #include "string/strspn/stprspn.h" diff --git a/lib/obscure.c b/lib/obscure.c index 9a53df85e3..3f0a4ca668 100644 --- a/lib/obscure.c +++ b/lib/obscure.c @@ -19,7 +19,7 @@ #include "prototypes.h" #include "defines.h" #include "getdef.h" -#include "string/ctype/strtoascii/strtolower.h" +#include "string/ctype/strtoascii.h" #include "string/memset/memzero.h" #include "string/sprintf/aprintf.h" #include "string/strcmp/streq.h" diff --git a/lib/string/README b/lib/string/README index 6c1094cd4a..c94ad0864a 100644 --- a/lib/string/README +++ b/lib/string/README @@ -75,21 +75,21 @@ ctype/ - Character classification and conversion functions if the character belongs to the category specified in the function name. - strchrisascii/ - The functions defined under this directory + strchrisascii.h + The functions defined in this file return true if the string has any characters that belong to the category specified in the function name. - strisascii/ - The functions defined under this directory + strisascii.h + The functions defined in this file return true if all of the characters of the string belong to the category specified in the function name and the string is not an empty string. - strtoascii/ - The functions defined under this directory + strtoascii.h + The functions defined in this file translate all characters in a string. memset/ - Memory zeroing diff --git a/lib/string/ctype/strchrisascii/strchriscntrl.c b/lib/string/ctype/strchrisascii.c similarity index 79% rename from lib/string/ctype/strchrisascii/strchriscntrl.c rename to lib/string/ctype/strchrisascii.c index ca77b4cfba..b9b7e919a9 100644 --- a/lib/string/ctype/strchrisascii/strchriscntrl.c +++ b/lib/string/ctype/strchrisascii.c @@ -4,7 +4,7 @@ #include "config.h" -#include "string/ctype/strchrisascii/strchriscntrl.h" +#include "string/ctype/strchrisascii.h" #include diff --git a/lib/string/ctype/strchrisascii/strchriscntrl.h b/lib/string/ctype/strchrisascii.h similarity index 78% rename from lib/string/ctype/strchrisascii/strchriscntrl.h rename to lib/string/ctype/strchrisascii.h index 8fe6e05752..a2be4e321a 100644 --- a/lib/string/ctype/strchrisascii/strchriscntrl.h +++ b/lib/string/ctype/strchrisascii.h @@ -2,8 +2,8 @@ // SPDX-License-Identifier: BSD-3-Clause -#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRCHRISASCII_STRCHRISCNTRL_H_ -#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRCHRISASCII_STRCHRISCNTRL_H_ +#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRCHRISASCII_H_ +#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRCHRISASCII_H_ #include "config.h" diff --git a/lib/string/ctype/strisascii/strisprint.c b/lib/string/ctype/strisascii.c similarity index 70% rename from lib/string/ctype/strisascii/strisprint.c rename to lib/string/ctype/strisascii.c index 47fb2a3bfe..564dac2504 100644 --- a/lib/string/ctype/strisascii/strisprint.c +++ b/lib/string/ctype/strisascii.c @@ -4,9 +4,10 @@ #include "config.h" -#include "string/ctype/strisascii/strisprint.h" +#include "string/ctype/strisascii.h" #include +extern inline bool strisdigit(const char *s); extern inline bool strisprint(const char *s); diff --git a/lib/string/ctype/strisascii/strisdigit.h b/lib/string/ctype/strisascii.h similarity index 58% rename from lib/string/ctype/strisascii/strisdigit.h rename to lib/string/ctype/strisascii.h index 1e4f69d2cd..1ee66c2fe3 100644 --- a/lib/string/ctype/strisascii/strisdigit.h +++ b/lib/string/ctype/strisascii.h @@ -2,8 +2,8 @@ // SPDX-License-Identifier: BSD-3-Clause -#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRISASCII_STRISDIGIT_H_ -#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRISASCII_STRISDIGIT_H_ +#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRISASCII_H_ +#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRISASCII_H_ #include "config.h" @@ -16,6 +16,7 @@ inline bool strisdigit(const char *s); +inline bool strisprint(const char *s); // strisdigit - string is [:digit:] @@ -29,4 +30,20 @@ strisdigit(const char *s) } +// strisprint - string is [:print:] +inline bool +strisprint(const char *s) +{ + if (streq(s, "")) + return false; + + for (; !streq(s, ""); s++) { + if (!isprint_c(*s)) + return false; + } + + return true; +} + + #endif // include guard diff --git a/lib/string/ctype/strisascii/strisdigit.c b/lib/string/ctype/strisascii/strisdigit.c deleted file mode 100644 index acd4522882..0000000000 --- a/lib/string/ctype/strisascii/strisdigit.c +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2024, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#include "config.h" - -#include "string/ctype/strisascii/strisdigit.h" - -#include - - -extern inline bool strisdigit(const char *s); diff --git a/lib/string/ctype/strisascii/strisprint.h b/lib/string/ctype/strisascii/strisprint.h deleted file mode 100644 index 652c6544d3..0000000000 --- a/lib/string/ctype/strisascii/strisprint.h +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRISASCII_STRISPRINT_H_ -#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRISASCII_STRISPRINT_H_ - - -#include "config.h" - -#include - -#include "string/ctype/isascii.h" -#include "string/strcmp/streq.h" - - -inline bool strisprint(const char *s); - - -// strisprint - string is [:print:] -inline bool -strisprint(const char *s) -{ - if (streq(s, "")) - return false; - - for (; !streq(s, ""); s++) { - if (!isprint_c(*s)) - return false; - } - - return true; -} - - -#endif // include guard diff --git a/lib/string/ctype/strtoascii/strtolower.c b/lib/string/ctype/strtoascii.c similarity index 78% rename from lib/string/ctype/strtoascii/strtolower.c rename to lib/string/ctype/strtoascii.c index 99ea4097ca..1e89acaaf5 100644 --- a/lib/string/ctype/strtoascii/strtolower.c +++ b/lib/string/ctype/strtoascii.c @@ -4,7 +4,7 @@ #include "config.h" -#include "string/ctype/strtoascii/strtolower.h" +#include "string/ctype/strtoascii.h" extern inline char *strtolower(char *str); diff --git a/lib/string/ctype/strtoascii/strtolower.h b/lib/string/ctype/strtoascii.h similarity index 61% rename from lib/string/ctype/strtoascii/strtolower.h rename to lib/string/ctype/strtoascii.h index d283fe1e87..c0c3be7177 100644 --- a/lib/string/ctype/strtoascii/strtolower.h +++ b/lib/string/ctype/strtoascii.h @@ -2,8 +2,8 @@ // SPDX-License-Identifier: BSD-3-Clause -#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRTOASCII_STRTOLOWER_H_ -#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRTOASCII_STRTOLOWER_H_ +#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRTOASCII_H_ +#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRTOASCII_H_ #include "config.h" @@ -16,9 +16,7 @@ inline char *strtolower(char *str); -// string convert-to lower-case -// Like tolower(3), but convert all characters in the string. -// Returns the input pointer. +// strtolower - string convert-to lower-case inline char * strtolower(char *str) { diff --git a/lib/subordinateio.c b/lib/subordinateio.c index 19c677dd89..e5f350c1df 100644 --- a/lib/subordinateio.c +++ b/lib/subordinateio.c @@ -24,7 +24,7 @@ #include "atoi/a2i.h" #include "atoi/getnum.h" #include "shadow/passwd/getpw.h" -#include "string/ctype/strisascii/strisdigit.h" +#include "string/ctype/strisascii.h" #include "string/sprintf/snprintf.h" #include "string/strcmp/streq.h" #include "string/strtok/strsep2arr.h" From 786b218943458f05ba5566466f481add2a0d9fb6 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 2 Jan 2026 21:37:55 +0100 Subject: [PATCH 04/14] lib/string/ctype/strisascii.h: strisprint(): Simplify implementation This also makes it consistent with strisdigit(). Signed-off-by: Alejandro Colomar --- lib/string/ctype/strisascii.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/string/ctype/strisascii.h b/lib/string/ctype/strisascii.h index 1ee66c2fe3..5ce5f6b0ab 100644 --- a/lib/string/ctype/strisascii.h +++ b/lib/string/ctype/strisascii.h @@ -37,12 +37,7 @@ strisprint(const char *s) if (streq(s, "")) return false; - for (; !streq(s, ""); s++) { - if (!isprint_c(*s)) - return false; - } - - return true; + return streq(stpspn(s, CTYPE_PRINT_C), ""); } From 89c453bb816bcbb02255990d2a14c9982c863bdb Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 2 Jan 2026 21:40:57 +0100 Subject: [PATCH 05/14] lib/string/ctype/strisascii.h: Compact definitions By being closer together, I find them more readable. The pattern and the differences are easier to spot. Signed-off-by: Alejandro Colomar --- lib/string/ctype/strisascii.h | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/lib/string/ctype/strisascii.h b/lib/string/ctype/strisascii.h index 5ce5f6b0ab..2f58f43ea5 100644 --- a/lib/string/ctype/strisascii.h +++ b/lib/string/ctype/strisascii.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024, Alejandro Colomar +// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar // SPDX-License-Identifier: BSD-3-Clause @@ -15,29 +15,19 @@ #include "string/strspn/stpspn.h" -inline bool strisdigit(const char *s); -inline bool strisprint(const char *s); +inline bool strisdigit(const char *s); // strisdigit - string is [:digit:] +inline bool strisprint(const char *s); // strisprint - string is [:print:] -// strisdigit - string is [:digit:] inline bool strisdigit(const char *s) { - if (streq(s, "")) - return false; - - return streq(stpspn(s, CTYPE_DIGIT_C), ""); + return !streq(s, "") && streq(stpspn(s, CTYPE_DIGIT_C), ""); } - - -// strisprint - string is [:print:] inline bool strisprint(const char *s) { - if (streq(s, "")) - return false; - - return streq(stpspn(s, CTYPE_PRINT_C), ""); + return !streq(s, "") && streq(stpspn(s, CTYPE_PRINT_C), ""); } From f31d65e66ca952c43e5603f759ff56ad0afebffd Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 2 Jan 2026 21:46:31 +0100 Subject: [PATCH 06/14] lib/: stris*(): Rename C-locale APIs with a _c suffix Signed-off-by: Alejandro Colomar --- lib/chkname.c | 4 ++-- lib/fields.c | 4 ++-- lib/string/ctype/strchrisascii.c | 2 +- lib/string/ctype/strchrisascii.h | 6 +++--- lib/string/ctype/strisascii.c | 6 +++--- lib/string/ctype/strisascii.h | 8 ++++---- lib/subordinateio.c | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/chkname.c b/lib/chkname.c index 18708defb8..09aab33bc8 100644 --- a/lib/chkname.c +++ b/lib/chkname.c @@ -51,8 +51,8 @@ is_valid_name(const char *name) || streq(name, "..") || strspn(name, "-") || strpbrk(name, " \"#',/:;") - || strchriscntrl(name) - || strisdigit(name)) + || strchriscntrl_c(name) + || strisdigit_c(name)) { errno = EINVAL; return false; diff --git a/lib/fields.c b/lib/fields.c index 77eb8c2d4f..af9bed077e 100644 --- a/lib/fields.c +++ b/lib/fields.c @@ -43,9 +43,9 @@ valid_field_(const char *field, const char *illegal) if (strpbrk(field, illegal)) return -1; - if (strchriscntrl(field)) + if (strchriscntrl_c(field)) return -1; - if (strisprint(field)) + if (strisprint_c(field)) return 0; if (streq(field, "")) return 0; diff --git a/lib/string/ctype/strchrisascii.c b/lib/string/ctype/strchrisascii.c index b9b7e919a9..5e25b23fa9 100644 --- a/lib/string/ctype/strchrisascii.c +++ b/lib/string/ctype/strchrisascii.c @@ -9,4 +9,4 @@ #include -extern inline bool strchriscntrl(const char *s); +extern inline bool strchriscntrl_c(const char *s); diff --git a/lib/string/ctype/strchrisascii.h b/lib/string/ctype/strchrisascii.h index a2be4e321a..04da16e9d3 100644 --- a/lib/string/ctype/strchrisascii.h +++ b/lib/string/ctype/strchrisascii.h @@ -14,12 +14,12 @@ #include "string/strcmp/streq.h" -inline bool strchriscntrl(const char *s); +inline bool strchriscntrl_c(const char *s); -// strchriscntrl - string character is [:cntrl:] +// strchriscntrl_c - string character is [:cntrl:] C-locale inline bool -strchriscntrl(const char *s) +strchriscntrl_c(const char *s) { for (; !streq(s, ""); s++) { unsigned char c = *s; diff --git a/lib/string/ctype/strisascii.c b/lib/string/ctype/strisascii.c index 564dac2504..c87c8f1b28 100644 --- a/lib/string/ctype/strisascii.c +++ b/lib/string/ctype/strisascii.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024, Alejandro Colomar +// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar // SPDX-License-Identifier: BSD-3-Clause @@ -9,5 +9,5 @@ #include -extern inline bool strisdigit(const char *s); -extern inline bool strisprint(const char *s); +extern inline bool strisdigit_c(const char *s); +extern inline bool strisprint_c(const char *s); diff --git a/lib/string/ctype/strisascii.h b/lib/string/ctype/strisascii.h index 2f58f43ea5..8e6b59b0bd 100644 --- a/lib/string/ctype/strisascii.h +++ b/lib/string/ctype/strisascii.h @@ -15,17 +15,17 @@ #include "string/strspn/stpspn.h" -inline bool strisdigit(const char *s); // strisdigit - string is [:digit:] -inline bool strisprint(const char *s); // strisprint - string is [:print:] +inline bool strisdigit_c(const char *s); // strisdigit - string is [:digit:] C-locale +inline bool strisprint_c(const char *s); // strisprint - string is [:print:] C-locale inline bool -strisdigit(const char *s) +strisdigit_c(const char *s) { return !streq(s, "") && streq(stpspn(s, CTYPE_DIGIT_C), ""); } inline bool -strisprint(const char *s) +strisprint_c(const char *s) { return !streq(s, "") && streq(stpspn(s, CTYPE_PRINT_C), ""); } diff --git a/lib/subordinateio.c b/lib/subordinateio.c index e5f350c1df..3ef5e69f68 100644 --- a/lib/subordinateio.c +++ b/lib/subordinateio.c @@ -908,7 +908,7 @@ static int append_uids(uid_t **uids, const char *owner, int n) int i; uid_t owner_uid; - if (strisdigit(owner)) { + if (strisdigit_c(owner)) { i = sscanf(owner, "%d", &owner_uid); if (i != 1) { // should not happen From 7e52af194a42650860c0453c015cdffc33584148 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sat, 3 Jan 2026 00:37:18 +0100 Subject: [PATCH 07/14] lib/string/ctype/strchrisascii.h: Use strpbrk(3) to simplify This compacts it into a one-liner, more similar to the strisascii_c() functions. Since we only use the argument once, we can even turn this into a macro. Signed-off-by: Alejandro Colomar --- lib/string/ctype/strchrisascii.c | 5 ----- lib/string/ctype/strchrisascii.h | 21 +++------------------ 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/lib/string/ctype/strchrisascii.c b/lib/string/ctype/strchrisascii.c index 5e25b23fa9..905430628a 100644 --- a/lib/string/ctype/strchrisascii.c +++ b/lib/string/ctype/strchrisascii.c @@ -5,8 +5,3 @@ #include "config.h" #include "string/ctype/strchrisascii.h" - -#include - - -extern inline bool strchriscntrl_c(const char *s); diff --git a/lib/string/ctype/strchrisascii.h b/lib/string/ctype/strchrisascii.h index 04da16e9d3..8fc775a8c0 100644 --- a/lib/string/ctype/strchrisascii.h +++ b/lib/string/ctype/strchrisascii.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar +// SPDX-FileCopyrightText: 2024-2026, Alejandro Colomar // SPDX-License-Identifier: BSD-3-Clause @@ -8,28 +8,13 @@ #include "config.h" -#include +#include #include "string/ctype/isascii.h" -#include "string/strcmp/streq.h" - - -inline bool strchriscntrl_c(const char *s); // strchriscntrl_c - string character is [:cntrl:] C-locale -inline bool -strchriscntrl_c(const char *s) -{ - for (; !streq(s, ""); s++) { - unsigned char c = *s; - - if (iscntrl_c(c)) - return true; - } - - return false; -} +#define strchriscntrl_c(s) (!!strpbrk(s, CTYPE_CNTRL_C)) #endif // include guard From 337ecf89e8503d9a450fbc6729fac37cfd2f281b Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sat, 3 Jan 2026 14:33:44 +0100 Subject: [PATCH 08/14] lib/fields.c: valid_field(): Check empty string before strisprint_c() This allows us to not depend on whether strisprint_c("") returns true or false. Signed-off-by: Alejandro Colomar --- lib/fields.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fields.c b/lib/fields.c index af9bed077e..6f0d77abc1 100644 --- a/lib/fields.c +++ b/lib/fields.c @@ -45,10 +45,10 @@ valid_field_(const char *field, const char *illegal) return -1; if (strchriscntrl_c(field)) return -1; - if (strisprint_c(field)) - return 0; if (streq(field, "")) return 0; + if (strisprint_c(field)) + return 0; return 1; // !ASCII } From dc539f1aec9dcc57ed20722d1dceff4443c301f8 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sat, 3 Jan 2026 14:37:43 +0100 Subject: [PATCH 09/14] lib/string/ctype/strisascii.*: Don't special-case "" It is not intuitive or clear what the right behavior should be for an empty string. If we define these APIs as "return true if all characters in the string belong to the specified character set", then an empty string should return true. On the other hand, if you ask me if an empty string is a numeric string, I might naively say no. It is irrelevant whether we return true or false for an empty string. All of the callers already handle correctly the case of an empty string. This makes the implementation simpler, using the argument only once. This allows implementing these as macros. Signed-off-by: Alejandro Colomar --- lib/string/README | 3 +-- lib/string/ctype/strisascii.c | 6 ------ lib/string/ctype/strisascii.h | 19 +++---------------- 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/lib/string/README b/lib/string/README index c94ad0864a..de182c9f2c 100644 --- a/lib/string/README +++ b/lib/string/README @@ -85,8 +85,7 @@ ctype/ - Character classification and conversion functions The functions defined in this file return true if all of the characters of the string - belong to the category specified in the function name - and the string is not an empty string. + belong to the category specified in the function name. strtoascii.h The functions defined in this file diff --git a/lib/string/ctype/strisascii.c b/lib/string/ctype/strisascii.c index c87c8f1b28..24e8a9cbb4 100644 --- a/lib/string/ctype/strisascii.c +++ b/lib/string/ctype/strisascii.c @@ -5,9 +5,3 @@ #include "config.h" #include "string/ctype/strisascii.h" - -#include - - -extern inline bool strisdigit_c(const char *s); -extern inline bool strisprint_c(const char *s); diff --git a/lib/string/ctype/strisascii.h b/lib/string/ctype/strisascii.h index 8e6b59b0bd..eb4d831bbd 100644 --- a/lib/string/ctype/strisascii.h +++ b/lib/string/ctype/strisascii.h @@ -8,27 +8,14 @@ #include "config.h" -#include - #include "string/ctype/isascii.h" #include "string/strcmp/streq.h" #include "string/strspn/stpspn.h" -inline bool strisdigit_c(const char *s); // strisdigit - string is [:digit:] C-locale -inline bool strisprint_c(const char *s); // strisprint - string is [:print:] C-locale - - -inline bool -strisdigit_c(const char *s) -{ - return !streq(s, "") && streq(stpspn(s, CTYPE_DIGIT_C), ""); -} -inline bool -strisprint_c(const char *s) -{ - return !streq(s, "") && streq(stpspn(s, CTYPE_PRINT_C), ""); -} +// strisascii_c - string is [:ascii:] C-locale +#define strisdigit_c(s) streq(stpspn(s, CTYPE_DIGIT_C), "") +#define strisprint_c(s) streq(stpspn(s, CTYPE_PRINT_C), "") #endif // include guard From 5a059fe667422210a16bbbf3cdb2abfa92275e7f Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 13 Mar 2026 01:16:26 +0100 Subject: [PATCH 10/14] lib/: Merge "lib/string/ctype/*" files even further Most of these are just one-liners, so they fit in less files, and that makes them even easier to compare all at once. Signed-off-by: Alejandro Colomar --- lib/Makefile.am | 8 ++------ lib/chkname.c | 3 +-- lib/fields.c | 3 +-- lib/obscure.c | 2 +- lib/string/ctype/isascii.h | 10 ++++++++++ lib/string/ctype/strchrisascii.c | 7 ------- lib/string/ctype/strchrisascii.h | 20 ------------------- lib/string/ctype/strisascii.c | 7 ------- lib/string/ctype/strisascii.h | 21 -------------------- lib/string/ctype/{strtoascii.c => toascii.c} | 2 +- lib/string/ctype/{strtoascii.h => toascii.h} | 4 ++-- lib/subordinateio.c | 2 +- 12 files changed, 19 insertions(+), 70 deletions(-) delete mode 100644 lib/string/ctype/strchrisascii.c delete mode 100644 lib/string/ctype/strchrisascii.h delete mode 100644 lib/string/ctype/strisascii.c delete mode 100644 lib/string/ctype/strisascii.h rename lib/string/ctype/{strtoascii.c => toascii.c} (82%) rename lib/string/ctype/{strtoascii.h => toascii.h} (80%) diff --git a/lib/Makefile.am b/lib/Makefile.am index a6c41abe4b..c613d37d84 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -193,12 +193,8 @@ libshadow_la_SOURCES = \ sssd.h \ string/ctype/isascii.c \ string/ctype/isascii.h \ - string/ctype/strchrisascii.c \ - string/ctype/strchrisascii.h \ - string/ctype/strisascii.c \ - string/ctype/strisascii.h \ - string/ctype/strtoascii.c \ - string/ctype/strtoascii.h \ + string/ctype/toascii.c \ + string/ctype/toascii.h \ string/memset/memzero.c \ string/memset/memzero.h \ string/sprintf/aprintf.c \ diff --git a/lib/chkname.c b/lib/chkname.c index 09aab33bc8..27f7a7d52d 100644 --- a/lib/chkname.c +++ b/lib/chkname.c @@ -33,8 +33,7 @@ #include "defines.h" #include "chkname.h" -#include "string/ctype/strchrisascii.h" -#include "string/ctype/strisascii.h" +#include "string/ctype/isascii.h" #include "string/strcmp/streq.h" #include "string/strcmp/strcaseeq.h" #include "sysconf.h" diff --git a/lib/fields.c b/lib/fields.c index 6f0d77abc1..568746fc8f 100644 --- a/lib/fields.c +++ b/lib/fields.c @@ -19,8 +19,7 @@ #include "io/fgets/fgets.h" #include "prototypes.h" -#include "string/ctype/strisascii.h" -#include "string/ctype/strchrisascii.h" +#include "string/ctype/isascii.h" #include "string/strcmp/streq.h" #include "string/strspn/stpspn.h" #include "string/strspn/stprspn.h" diff --git a/lib/obscure.c b/lib/obscure.c index 3f0a4ca668..342bb812d6 100644 --- a/lib/obscure.c +++ b/lib/obscure.c @@ -19,7 +19,7 @@ #include "prototypes.h" #include "defines.h" #include "getdef.h" -#include "string/ctype/strtoascii.h" +#include "string/ctype/toascii.h" #include "string/memset/memzero.h" #include "string/sprintf/aprintf.h" #include "string/strcmp/streq.h" diff --git a/lib/string/ctype/isascii.h b/lib/string/ctype/isascii.h index 8a1b47fcff..6500717c6a 100644 --- a/lib/string/ctype/isascii.h +++ b/lib/string/ctype/isascii.h @@ -11,6 +11,7 @@ #include #include "string/strcmp/streq.h" +#include "string/strspn/stpspn.h" #define CTYPE_CNTRL_C \ @@ -46,4 +47,13 @@ #define isxdigit_c(c) (!streq(strchrnul(CTYPE_XDIGIT_C, c), "")) +// strisascii_c - string is [:ascii:] C-locale +#define strisdigit_c(s) streq(stpspn(s, CTYPE_DIGIT_C), "") +#define strisprint_c(s) streq(stpspn(s, CTYPE_PRINT_C), "") + + +// strchriscntrl_c - string character is [:cntrl:] C-locale +#define strchriscntrl_c(s) (!!strpbrk(s, CTYPE_CNTRL_C)) + + #endif // include guard diff --git a/lib/string/ctype/strchrisascii.c b/lib/string/ctype/strchrisascii.c deleted file mode 100644 index 905430628a..0000000000 --- a/lib/string/ctype/strchrisascii.c +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2024, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#include "config.h" - -#include "string/ctype/strchrisascii.h" diff --git a/lib/string/ctype/strchrisascii.h b/lib/string/ctype/strchrisascii.h deleted file mode 100644 index 8fc775a8c0..0000000000 --- a/lib/string/ctype/strchrisascii.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: 2024-2026, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRCHRISASCII_H_ -#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRCHRISASCII_H_ - - -#include "config.h" - -#include - -#include "string/ctype/isascii.h" - - -// strchriscntrl_c - string character is [:cntrl:] C-locale -#define strchriscntrl_c(s) (!!strpbrk(s, CTYPE_CNTRL_C)) - - -#endif // include guard diff --git a/lib/string/ctype/strisascii.c b/lib/string/ctype/strisascii.c deleted file mode 100644 index 24e8a9cbb4..0000000000 --- a/lib/string/ctype/strisascii.c +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#include "config.h" - -#include "string/ctype/strisascii.h" diff --git a/lib/string/ctype/strisascii.h b/lib/string/ctype/strisascii.h deleted file mode 100644 index eb4d831bbd..0000000000 --- a/lib/string/ctype/strisascii.h +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRISASCII_H_ -#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRISASCII_H_ - - -#include "config.h" - -#include "string/ctype/isascii.h" -#include "string/strcmp/streq.h" -#include "string/strspn/stpspn.h" - - -// strisascii_c - string is [:ascii:] C-locale -#define strisdigit_c(s) streq(stpspn(s, CTYPE_DIGIT_C), "") -#define strisprint_c(s) streq(stpspn(s, CTYPE_PRINT_C), "") - - -#endif // include guard diff --git a/lib/string/ctype/strtoascii.c b/lib/string/ctype/toascii.c similarity index 82% rename from lib/string/ctype/strtoascii.c rename to lib/string/ctype/toascii.c index 1e89acaaf5..5f8cc0c7b2 100644 --- a/lib/string/ctype/strtoascii.c +++ b/lib/string/ctype/toascii.c @@ -4,7 +4,7 @@ #include "config.h" -#include "string/ctype/strtoascii.h" +#include "string/ctype/toascii.h" extern inline char *strtolower(char *str); diff --git a/lib/string/ctype/strtoascii.h b/lib/string/ctype/toascii.h similarity index 80% rename from lib/string/ctype/strtoascii.h rename to lib/string/ctype/toascii.h index c0c3be7177..440a242223 100644 --- a/lib/string/ctype/strtoascii.h +++ b/lib/string/ctype/toascii.h @@ -2,8 +2,8 @@ // SPDX-License-Identifier: BSD-3-Clause -#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_STRTOASCII_H_ -#define SHADOW_INCLUDE_LIB_STRING_CTYPE_STRTOASCII_H_ +#ifndef SHADOW_INCLUDE_LIB_STRING_CTYPE_TOASCII_H_ +#define SHADOW_INCLUDE_LIB_STRING_CTYPE_TOASCII_H_ #include "config.h" diff --git a/lib/subordinateio.c b/lib/subordinateio.c index 3ef5e69f68..65877daf05 100644 --- a/lib/subordinateio.c +++ b/lib/subordinateio.c @@ -24,7 +24,7 @@ #include "atoi/a2i.h" #include "atoi/getnum.h" #include "shadow/passwd/getpw.h" -#include "string/ctype/strisascii.h" +#include "string/ctype/isascii.h" #include "string/sprintf/snprintf.h" #include "string/strcmp/streq.h" #include "string/strtok/strsep2arr.h" From 42e056d46929665cba85d8c90da5e2c17a85a7e1 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 23 Dec 2024 18:36:31 +0100 Subject: [PATCH 11/14] lib/string/ctype/isascii.h: ispfchar_c(): Add macro This function returns true if the input character is a character from the POSIX portable filename character set. Link: Signed-off-by: Alejandro Colomar --- lib/string/ctype/isascii.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/string/ctype/isascii.h b/lib/string/ctype/isascii.h index 6500717c6a..85863bcf0d 100644 --- a/lib/string/ctype/isascii.h +++ b/lib/string/ctype/isascii.h @@ -30,6 +30,7 @@ #define CTYPE_PRINT_C CTYPE_GRAPH_C " " #define CTYPE_XDIGIT_C CTYPE_DIGIT_C "abcdefABCDEF" #define CTYPE_ASCII_C CTYPE_PRINT_C CTYPE_CNTRL_C /*NUL*/ +#define CTYPE_PFCHAR_C CTYPE_ALNUM_C "._-" // portable filename character set // isascii_c - is [:ascii:] C-locale @@ -45,6 +46,7 @@ #define isgraph_c(c) (!streq(strchrnul(CTYPE_GRAPH_C, c), "")) #define isprint_c(c) (!streq(strchrnul(CTYPE_PRINT_C, c), "")) #define isxdigit_c(c) (!streq(strchrnul(CTYPE_XDIGIT_C, c), "")) +#define ispfchar_c(c) (!streq(strchrnul(CTYPE_PFCHAR_C, c), "")) // strisascii_c - string is [:ascii:] C-locale From 277c74a4e23d5da72e0a35492dc9791387060b8c Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 23 Dec 2024 15:25:48 +0100 Subject: [PATCH 12/14] lib/chkname.c: is_valid_name(): Use isalnum(3) instead of its pattern Signed-off-by: Alejandro Colomar --- lib/chkname.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/chkname.c b/lib/chkname.c index 27f7a7d52d..a23e121a4c 100644 --- a/lib/chkname.c +++ b/lib/chkname.c @@ -69,9 +69,7 @@ is_valid_name(const char *name) * sake of Samba 3.x "add machine script" */ - if (!((*name >= 'a' && *name <= 'z') || - (*name >= 'A' && *name <= 'Z') || - (*name >= '0' && *name <= '9') || + if (!(isalnum(*name) || *name == '_' || *name == '.')) { @@ -80,9 +78,7 @@ is_valid_name(const char *name) } while (!streq(++name, "")) { - if (!((*name >= 'a' && *name <= 'z') || - (*name >= 'A' && *name <= 'Z') || - (*name >= '0' && *name <= '9') || + if (!(isalnum(*name) || *name == '_' || *name == '.' || *name == '-' || From ada55b69fa072d1e2f2af0bcd6da148f25f34bfc Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 23 Dec 2024 17:30:57 +0100 Subject: [PATCH 13/14] lib/chkname.c: is_valid_name(): Split Samba check Signed-off-by: Alejandro Colomar --- lib/chkname.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/chkname.c b/lib/chkname.c index a23e121a4c..17f277267b 100644 --- a/lib/chkname.c +++ b/lib/chkname.c @@ -78,11 +78,13 @@ is_valid_name(const char *name) } while (!streq(++name, "")) { + if (streq(name, "$")) // Samba + return true; + if (!(isalnum(*name) || *name == '_' || *name == '.' || - *name == '-' || - streq(name, "$") + *name == '-' )) { errno = EILSEQ; From 0d5545960b6718e00835891d67e8169df945fd03 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 23 Dec 2024 18:41:06 +0100 Subject: [PATCH 14/14] lib/chkname.c: is_valid_name(): Use ispfchar_c() to simplify In the first case, we can do the transformation because a few lines above, we explicitly reject a name starting with a '-'. In the second case, we're obviously using ispfchar_c() instead of its pattern. Signed-off-by: Alejandro Colomar --- lib/chkname.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/chkname.c b/lib/chkname.c index 17f277267b..a33e5cb9f8 100644 --- a/lib/chkname.c +++ b/lib/chkname.c @@ -69,10 +69,7 @@ is_valid_name(const char *name) * sake of Samba 3.x "add machine script" */ - if (!(isalnum(*name) || - *name == '_' || - *name == '.')) - { + if (!ispfchar_c(*name)) { errno = EILSEQ; return false; } @@ -81,12 +78,7 @@ is_valid_name(const char *name) if (streq(name, "$")) // Samba return true; - if (!(isalnum(*name) || - *name == '_' || - *name == '.' || - *name == '-' - )) - { + if (!ispfchar_c(*name)) { errno = EILSEQ; return false; }