summaryrefslogtreecommitdiffstats
path: root/lib/util/charset
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2014-08-01 21:38:59 -0700
committerJeremy Allison <jra@samba.org>2014-08-06 01:05:14 +0200
commitdfe8dd87e15bec453c7d3a80c4c707d3f2c7b597 (patch)
tree0c89a1a8c694ea2528bdc2f763569630f421ad0d /lib/util/charset
parent9380478a0b292bcb0c11987a88803a37a064d618 (diff)
downloadsamba-dfe8dd87e15bec453c7d3a80c4c707d3f2c7b597.tar.gz
samba-dfe8dd87e15bec453c7d3a80c4c707d3f2c7b597.tar.xz
samba-dfe8dd87e15bec453c7d3a80c4c707d3f2c7b597.zip
lib: strings: Fix the behavior of strncasecmp_m_handle() in the face of bad conversions.
When either string has a bad conversion, we fall back to doing raw ascii byte comparisons using strcasecmp(). This is wrong - we should fall back to strncasecmp. The problem is we've already stepped past the character that failed the conversion, so we're not re-testing those characters for comparison. This can have the effect of causing strncasecmp_m_handle() to report that two strings are identical when they are not, if the failed conversion takes place at the end of the string. The correct behavior is to step back to the point of the string(s) that failed the conversion, and continue the test from there. This is a litle trickier than the previous fix, as it requires converting the incoming n variable from remaining characters to compare to remaining bytes to compare. As bytes are always the smallest character size (1 byte) then it's safe to convert the remaining characters to check by decrementing the source string by the last character length (in bytes) and incrementing the remaining bytes to scan by the same value, then calling strncasecmp() with the stepped back strings remaining. Signed-off-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/util/charset')
-rw-r--r--lib/util/charset/util_str.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/lib/util/charset/util_str.c b/lib/util/charset/util_str.c
index 1810e2429f..f62c9998b3 100644
--- a/lib/util/charset/util_str.c
+++ b/lib/util/charset/util_str.c
@@ -116,8 +116,33 @@ _PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
if (c1 == INVALID_CODEPOINT ||
c2 == INVALID_CODEPOINT) {
- /* what else can we do?? */
- return strcasecmp(s1, s2);
+ /*
+ * Fall back to byte
+ * comparison. We must
+ * step back by the codepoint
+ * length we just incremented
+ * by - otherwise we are not
+ * checking the bytes that
+ * failed the conversion.
+ */
+ s1 -= size1;
+ s2 -= size2;
+ /*
+ * n was specified in characters,
+ * now we must convert it to bytes.
+ * As bytes are the smallest
+ * character unit, the following
+ * increment and strncasecmp is always
+ * safe.
+ *
+ * The source string was already known
+ * to be n characters long, so we are
+ * guaranteed to be able to look at the
+ * (n remaining + size1) bytes from the
+ * new (s1 - size1) position).
+ */
+ n += size1;
+ return strncasecmp(s1, s2, n);
}
if (toupper_m(c1) != toupper_m(c2)) {