Previously, if "b" was length 127, the loop would terminate after
copying bytes 0..125. The final for loop increment would set i=126.
Then, "tmp[i+1] = 0" would nul-terminate the string at byte 127. So
byte 126 would be unset.
Note that since none of the Capabilities mutt were passing are that
long, the bug wouldn't matter, but it was a confusing and buggy
function in any case. :D
Thanks to Acts1631 for the bug report.
Thanks to Alejandro Colomar for his discussion and proposed patches,
which motivated the use of strcspn() here, along with defining
ASCII_WS.
Also thanks to Kurt Hackenberg and Ian Collier for their discussion
and proposals, leading to the removal of the tmp[] array completely.
---
I'm tossing this out for review. I have compiled and tested it, but
I'm tired enough that I probably shouldn't be sending patches right now.
But I'll email this out for semi-official review, and I will take
another look and test it a bit more over the next few days!
imap/util.c | 23 ++++++-----------------
lib.h | 1 +
2 files changed, 7 insertions(+), 17 deletions(-)
diff --git a/imap/util.c b/imap/util.c
index 9b6ef7b4..66b41917 100644
--- a/imap/util.c
+++ b/imap/util.c
@@ -880,26 +880,15 @@ void imap_unmunge_mbox_name(IMAP_DATA *idata, char *s)
FREE(&buf);
}
-/* imap_wordcasecmp: find word a in word list b */
+/* imap_wordcasecmp: compares word a against the initial ASCII_WS
+ * delimited word in word list b */
int imap_wordcasecmp(const char *a, const char *b)
{
- char tmp[SHORT_STRING];
- const char *s = b;
- int i;
+ size_t a_len, b_len;
- tmp[SHORT_STRING-1] = 0;
- for (i=0;i < SHORT_STRING-2;i++,s++)
- {
- if (!*s || IS_ASCII_WS(*s))
- {
- tmp[i] = 0;
- break;
- }
- tmp[i] = *s;
- }
- tmp[i+1] = 0;
-
- return ascii_strcasecmp(a, tmp);
+ a_len = mutt_strlen(a);
+ b_len = b ? strcspn(b, ASCII_WS) : 0;
+ return ascii_strncasecmp(a, b, MAX(a_len, b_len));
}
/*
diff --git a/lib.h b/lib.h
index 830459d6..72e3a498 100644
--- a/lib.h
+++ b/lib.h
@@ -113,6 +113,7 @@
* 0x09-0x0d (\t \n \v \f \r)
* 0x20 (space)
*/
+#define ASCII_WS " \t\n\v\f\r"
#define IS_ASCII_WS(c) ((9 <= (c) && (c) <= 13) || (c) == 32)
#define SKIP_ASCII_WS(c) while (IS_ASCII_WS(*(c))) c++;
--
2.54.0