From: Karel Zak Date: Thu, 6 May 2021 14:35:50 +0000 (+0200) Subject: lib/jsonwrt: don't use ctype.h for ASCII chars X-Git-Tag: v2.37-rc2~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=64a89adaa16461bd58730c1408b30aa7244b4f66;p=thirdparty%2Futil-linux.git lib/jsonwrt: don't use ctype.h for ASCII chars tolower() does not work "as expected" for tr_TR.UTF-8 (Turkish). Fortunately, we need to convert only objects and variables names in JSON output, and this is always old good ASCII. Anyway, for more details: $ cat a.c #include #include #include int main(void) { int in, out; setlocale(LC_ALL, ""); in ='I'; out = tolower(in); printf("%1$c [%1$d] --> %2$c [%2$d]\n", in, out); return 0; } $ make a cc a.c -o a $ LANG=en_US.utf8 ./a I [73] --> i [105] $ LANG=tr_TR.UTF-8 ./a I [73] --> I [73] Fixes: https://github.com/karelzak/util-linux/issues/1302 Signed-off-by: Karel Zak --- diff --git a/lib/jsonwrt.c b/lib/jsonwrt.c index 92d64f7464..f2003e8083 100644 --- a/lib/jsonwrt.c +++ b/lib/jsonwrt.c @@ -8,6 +8,8 @@ */ #include #include +#include +#include #include "c.h" #include "jsonwrt.h" @@ -31,7 +33,7 @@ static void fputs_quoted_case_json(const char *data, FILE *out, int dir) fputc('"', out); for (p = data; p && *p; p++) { - const unsigned char c = (unsigned char) *p; + const unsigned int c = (unsigned int) *p; /* From http://www.json.org * @@ -49,8 +51,17 @@ static void fputs_quoted_case_json(const char *data, FILE *out, int dir) /* All non-control characters OK; do the case swap as required. */ if (c >= 0x20) { - fputc(dir == 1 ? toupper(c) : - dir == -1 ? tolower(c) : *p, out); + /* + * Don't use locale sensitive ctype.h functions for regular + * ASCII chars, because for example with Turkish locale + * (aka LANG=tr_TR.UTF-8) toupper('I') returns 'I'. + */ + if (c <= 127) + fputc(dir == 1 ? c_toupper(c) : + dir == -1 ? c_tolower(c) : *p, out); + else + fputc(dir == 1 ? toupper(c) : + dir == -1 ? tolower(c) : *p, out); continue; }