git__strcasecmp: treat input bytes as unsigned Treat input bytes as unsigned before doing arithmetic on them, lest we look at some non-ASCII byte (like a UTF-8 character) as a negative value and perform the comparison incorrectly.
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
diff --git a/src/util.c b/src/util.c
index 6bb7d03..b8d6cf5 100644
--- a/src/util.c
+++ b/src/util.c
@@ -173,7 +173,7 @@ int git__strcasecmp(const char *a, const char *b)
{
while (*a && *b && tolower(*a) == tolower(*b))
++a, ++b;
- return (tolower(*a) - tolower(*b));
+ return ((unsigned char)tolower(*a) - (unsigned char)tolower(*b));
}
int git__strcasesort_cmp(const char *a, const char *b)
@@ -193,7 +193,7 @@ int git__strcasesort_cmp(const char *a, const char *b)
}
if (*a || *b)
- return tolower(*a) - tolower(*b);
+ return (unsigned char)tolower(*a) - (unsigned char)tolower(*b);
return cmp;
}
diff --git a/tests/core/string.c b/tests/core/string.c
index ec95756..c6c2d95 100644
--- a/tests/core/string.c
+++ b/tests/core/string.c
@@ -39,3 +39,41 @@ void test_core_string__2(void)
cl_assert(git__strcasesort_cmp("BAR", "foo") < 0);
cl_assert(git__strcasesort_cmp("fooBar", "foobar") < 0);
}
+
+void test_core_string__strcmp(void)
+{
+ cl_assert(git__strcmp("", "") == 0);
+ cl_assert(git__strcmp("foo", "foo") == 0);
+ cl_assert(git__strcmp("Foo", "foo") < 0);
+ cl_assert(git__strcmp("foo", "FOO") > 0);
+ cl_assert(git__strcmp("foo", "fOO") > 0);
+
+ cl_assert(strcmp("rt\303\202of", "rt dev\302\266h") > 0);
+ cl_assert(strcmp("e\342\202\254ghi=", "et") > 0);
+ cl_assert(strcmp("rt dev\302\266h", "rt\303\202of") < 0);
+ cl_assert(strcmp("et", "e\342\202\254ghi=") < 0);
+
+ cl_assert(git__strcmp("rt\303\202of", "rt dev\302\266h") > 0);
+ cl_assert(git__strcmp("e\342\202\254ghi=", "et") > 0);
+ cl_assert(git__strcmp("rt dev\302\266h", "rt\303\202of") < 0);
+ cl_assert(git__strcmp("et", "e\342\202\254ghi=") < 0);
+}
+
+void test_core_string__strcasecmp(void)
+{
+ cl_assert(git__strcasecmp("", "") == 0);
+ cl_assert(git__strcasecmp("foo", "foo") == 0);
+ cl_assert(git__strcasecmp("foo", "Foo") == 0);
+ cl_assert(git__strcasecmp("foo", "FOO") == 0);
+ cl_assert(git__strcasecmp("foo", "fOO") == 0);
+
+ cl_assert(strcasecmp("rt\303\202of", "rt dev\302\266h") > 0);
+ cl_assert(strcasecmp("e\342\202\254ghi=", "et") > 0);
+ cl_assert(strcasecmp("rt dev\302\266h", "rt\303\202of") < 0);
+ cl_assert(strcasecmp("et", "e\342\202\254ghi=") < 0);
+
+ cl_assert(git__strcasecmp("rt\303\202of", "rt dev\302\266h") > 0);
+ cl_assert(git__strcasecmp("e\342\202\254ghi=", "et") > 0);
+ cl_assert(git__strcasecmp("rt dev\302\266h", "rt\303\202of") < 0);
+ cl_assert(git__strcasecmp("et", "e\342\202\254ghi=") < 0);
+}