summaryrefslogtreecommitdiff
path: root/system/musl/signed-wchar_t-fixes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/musl/signed-wchar_t-fixes.patch')
-rw-r--r--system/musl/signed-wchar_t-fixes.patch77
1 files changed, 77 insertions, 0 deletions
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 <gabravier@gmail.com>
+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 <wchar.h>
+ #include <stdio.h>
+
+ 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
+