From d80109dd5e960ab007911b73a77161e3e8047798 Mon Sep 17 00:00:00 2001
From: Benno Schulenberg <bensberg@justemail.net>
Date: Wed, 27 Jul 2016 22:15:34 +0200
Subject: [PATCH] chars: properly compare strings of different lengths

That is: don't run towlower() on the two differing bytes when having
reached the end of one of the strings.

This fixes https://savannah.gnu.org/bugs/?48700.

In the bargain, don't do the conversion to lowercase twice.

Furthermore, persist when encountering invalid byte sequences --
until finding bytes that differ.
---
 src/chars.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/chars.c b/src/chars.c
index d80bd3af..4cfe807b 100644
--- a/src/chars.c
+++ b/src/chars.c
@@ -514,28 +514,37 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
 
 	while (*s1 != '\0' && *s2 != '\0' && n > 0) {
 	    bool bad1 = FALSE, bad2 = FALSE;
+	    int difference;
 
 	    if (mbtowc(&wc1, s1, MB_CUR_MAX) < 0) {
 		mbtowc_reset();
-		wc1 = (unsigned char)*s1;
 		bad1 = TRUE;
 	    }
 
 	    if (mbtowc(&wc2, s2, MB_CUR_MAX) < 0) {
 		mbtowc_reset();
-		wc2 = (unsigned char)*s2;
 		bad2 = TRUE;
 	    }
 
-	    if (bad1 != bad2 || towlower(wc1) != towlower(wc2))
-		break;
+	    if (bad1 || bad2) {
+		if (*s1 != *s2)
+		    return (unsigned char)*s1 - (unsigned char)*s2;
+
+		s1++; s2++; n--;
+		continue;
+	    }
+
+	    difference = towlower(wc1) - towlower(wc2);
+
+	    if (difference != 0)
+		return difference;
 
 	    s1 += move_mbright(s1, 0);
 	    s2 += move_mbright(s2, 0);
 	    n--;
 	}
 
-	return (n > 0) ? towlower(wc1) - towlower(wc2) : 0;
+	return (n > 0) ? ((unsigned char)*s1 - (unsigned char)*s2) : 0;
     } else
 #endif
 	return strncasecmp(s1, s2, n);
-- 
GitLab