From 77c68c5602562321c06e299f348d801cc701b222 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 1 Oct 2020 10:51:40 -0400 Subject: [PATCH] Fix correctness error in CaseInsensitiveCompare::operator() by rolling my own implementation. --- include/string.hpp | 1 + src/string.cpp | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/string.hpp b/include/string.hpp index 3c3214b3..f082646c 100644 --- a/include/string.hpp +++ b/include/string.hpp @@ -45,6 +45,7 @@ Throws std::runtime_error if string is invalid. std::vector fromBase64(const std::string& str); struct CaseInsensitiveCompare { + /** Returns whether `a < b` using case-insensitive lexical comparison. */ bool operator()(const std::string& a, const std::string& b) const; }; diff --git a/src/string.cpp b/src/string.cpp index d75f5595..11412f8e 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -184,12 +184,16 @@ std::vector fromBase64(const std::string& str) { bool CaseInsensitiveCompare::operator()(const std::string& a, const std::string& b) const { - if (a.size() != b.size()) - return false; - auto f = [](unsigned char a, unsigned char b) { - return std::tolower(a) == std::tolower(b); - }; - return std::equal(a.begin(), a.end(), b.begin(), f); + for (size_t i = 0;; i++) { + char ai = std::tolower(a[i]); + char bi = std::tolower(b[i]); + if (ai < bi) + return true; + if (ai > bi) + return false; + if (!ai || !bi) + return false; + } }