From 0c5716b886f2a251f506ffbf3799a3f9199b2592 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 12 Jan 2023 05:29:55 +0000 Subject: system/musl: Fix wchar_t issue --- system/musl/signed-wchar_t-fixes.patch | 77 ++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 system/musl/signed-wchar_t-fixes.patch (limited to 'system/musl/signed-wchar_t-fixes.patch') diff --git a/system/musl/signed-wchar_t-fixes.patch b/system/musl/signed-wchar_t-fixes.patch new file mode 100644 index 000000000..0d5309315 --- /dev/null +++ b/system/musl/signed-wchar_t-fixes.patch @@ -0,0 +1,77 @@ +From 99b84a793669c69acc705a61d339441b50bd09a8 Mon Sep 17 00:00:00 2001 +From: Gabriel Ravier +Date: Wed, 4 Jan 2023 16:07:19 +0100 +Subject: [PATCH] fix return value of wcs{,n}cmp for near-limits signed wchar_t values + +The standard states that: + + > Unless explicitly stated otherwise, the functions described in + this subclause order two wide characters the same way as two + integers of the underlying integer type designated by `wchar_t`. + > [...] + > The `wcscmp` function returns an integer greater than, equal to, + or less than zero, accordingly as the wide string pointed to by s1 + is greater than, equal to, or less than the wide string pointed to + by s2. + > The `wcsncmp` function returns an integer greater than, equal to, + or less than zero, accordingly as the possibly null-terminated + array pointed to by s1 is greater than, equal to, or less than the + possibly null-terminated array pointed to by s2 + - N3047 (latest C draft as of the time of writing) + +Yet a simple test program such as this: + + #include + #include + + int main() + { + wchar_t str1[2] = { WCHAR_MAX, L'\0' }; + wchar_t str2[2] = { WCHAR_MIN, L'\0' }; + + printf("%d\n", wcscmp(str1, str2)); + printf("%d\n", wcsncmp(str1, str2, 1)); + } + +Will fail to run correctly according to this specification on musl (on +targets that have signed wchar_t), as it will print -1 instead of +1 (it should print 1, since WCHAR_MAX > WCHAR_MIN). + +This appears to be due to the fact that musl uses a simple subtraction +to implement wcscmp and wcsncmp, which may result in an overflow. + +This patch fixes this by replacing the subtraction with a little bit +of code that orders the characters correctly, returning -1 if the +character from the first string is smaller than the one from the +second, 0 if they are equal and 1 if the character from the first +string is larger than the one from the second +--- + src/string/wcscmp.c | 2 +- + src/string/wcsncmp.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/string/wcscmp.c b/src/string/wcscmp.c +index 26eeee70..286ec3ea 100644 +--- a/src/string/wcscmp.c ++++ b/src/string/wcscmp.c +@@ -3,5 +3,5 @@ + int wcscmp(const wchar_t *l, const wchar_t *r) + { + for (; *l==*r && *l && *r; l++, r++); +- return *l - *r; ++ return *l < *r ? -1 : *l > *r; + } +diff --git a/src/string/wcsncmp.c b/src/string/wcsncmp.c +index 4ab32a92..2b3558bf 100644 +--- a/src/string/wcsncmp.c ++++ b/src/string/wcsncmp.c +@@ -3,5 +3,5 @@ + int wcsncmp(const wchar_t *l, const wchar_t *r, size_t n) + { + for (; n && *l==*r && *l && *r; n--, l++, r++); +- return n ? *l - *r : 0; ++ return n ? (*l < *r ? -1 : *l > *r) : 0; + } +-- +2.38.1 + -- cgit v1.2.3-60-g2f50