1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
From: Karel Zak <kzak@redhat.com>
Date: Wed, 2 Apr 2025 11:00:47 +0200
Subject: include/cctype: fix string comparison
Reimplement c_strcasecmp() and c_strncasecmp() to be libc compatible
and fix c_strncasecmp() to avoid \0 misinterpretation. The original
implementation was pretty stupid (sorry).
Signed-off-by: Karel Zak <kzak@redhat.com>
(cherry picked from commit 259157b0c1a00806ff75188325e40ba10adf12ce)
---
include/cctype.h | 55 +++++++++++++++++++++++++++++++++++++------------------
1 file changed, 37 insertions(+), 18 deletions(-)
diff --git a/include/cctype.h b/include/cctype.h
index b673b6c..e55c008 100644
--- a/include/cctype.h
+++ b/include/cctype.h
@@ -23,6 +23,9 @@
#ifndef UTIL_LINUX_CCTYPE_H
#define UTIL_LINUX_CCTYPE_H
+#include <stddef.h>
+#include <limits.h>
+
/**
* The functions defined in this file assume the "C" locale and a character
* set without diacritics (ASCII-US or EBCDIC-US or something like that).
@@ -317,38 +320,54 @@ static inline int c_toupper (int c)
}
}
+#define C_CTYPE_CMP(c1, c2) (((c1) > (c2)) - ((c1) < (c2)))
+
static inline int c_strncasecmp(const char *a, const char *b, size_t n)
{
- int res = 0;
+ const unsigned char *p1 = (const unsigned char *) a;
+ const unsigned char *p2 = (const unsigned char *) b;
+ unsigned char x, y;
- for (; n > 0; a++, b++, n--) {
- unsigned int x = (unsigned int) *a;
- unsigned int y = (unsigned int) *b;
+ if (n == 0 || p1 == p2)
+ return 0;
- res = c_tolower(x) - c_tolower(y);
- if (res)
- break;
- }
- return res;
+ do {
+ x = c_tolower(*p1);
+ y = c_tolower(*p2);
+
+ if (--n == 0 || x == '\0')
+ break;
+ ++p1, ++p2;
+ } while (x == y);
+
+ if (UCHAR_MAX <= INT_MAX)
+ return x - y;
+
+ return C_CTYPE_CMP(x, y);
}
static inline int c_strcasecmp(const char *a, const char *b)
{
- int res = 0;
+ const unsigned char *p1 = (const unsigned char *) a;
+ const unsigned char *p2 = (const unsigned char *) b;
+ unsigned char x, y;
- if (a == b)
+ if (p1 == p2)
return 0;
- for (; *a != '\0'; a++, b++) {
- unsigned int x = (unsigned int) *a;
- unsigned int y = (unsigned int) *b;
+ do {
+ x = c_tolower(*p1);
+ y = c_tolower(*p2);
- res = c_tolower(x) - c_tolower(y);
- if (res)
+ if (x == '\0')
break;
- }
+ ++p1, ++p2;
+ } while (x == y);
- return res;
+ if (UCHAR_MAX <= INT_MAX)
+ return x - y;
+
+ return C_CTYPE_CMP(x, y);
}
#endif /* UTIL_LINUX_CCTYPE_H */
|