From 8acd84fdc8610dac867b9fc7e12106fd2c7ce048 Mon Sep 17 00:00:00 2001 From: ds Date: Fri, 11 Sep 2020 16:01:33 +0300 Subject: [PATCH] fix: terrorist behaviour on ES maps with buyzone. (fixes #155). fix: help commands causing host overflow when translated. crlib: use fnv1a for string hashes. crlib: add hash () method to String & StringRef classes. --- ext/crlib/cr-hashmap.h | 24 +++--------------------- ext/crlib/cr-string.h | 23 +++++++++++++++-------- inc/config.h | 2 +- src/botlib.cpp | 2 +- src/config.cpp | 24 +++++++++--------------- src/control.cpp | 8 ++++++-- 6 files changed, 35 insertions(+), 48 deletions(-) diff --git a/ext/crlib/cr-hashmap.h b/ext/crlib/cr-hashmap.h index 0fc36e2..cc28bac 100644 --- a/ext/crlib/cr-hashmap.h +++ b/ext/crlib/cr-hashmap.h @@ -26,37 +26,19 @@ template struct Hash; template <> struct Hash { uint32 operator () (const String &key) const noexcept { - auto str = const_cast (key.chars ()); - uint32 hash = 0; - - while (*str++) { - hash = ((hash << 5) + hash) + *str; - } - return hash; + return key.hash (); } }; template <> struct Hash { uint32 operator () (const StringRef &key) const noexcept { - auto str = const_cast (key.chars ()); - uint32 hash = 0; - - while (*str++) { - hash = ((hash << 5) + hash) + *str; - } - return hash; + return key.hash (); } }; template <> struct Hash { uint32 operator () (const char *key) const noexcept { - auto str = const_cast (key); - uint32 hash = 0; - - while (*str++) { - hash = ((hash << 5) + hash) + *str; - } - return hash; + return StringRef::fnv1a32 (key); } }; diff --git a/ext/crlib/cr-string.h b/ext/crlib/cr-string.h index 04b7b8e..d20dabb 100644 --- a/ext/crlib/cr-string.h +++ b/ext/crlib/cr-string.h @@ -59,14 +59,13 @@ CR_EXPOSE_GLOBAL_SINGLETON (SNPrintfWrap, fmtwrap); // simple non-owning string class like std::string_view class StringRef { private: - static constexpr size_t strLength (const char *cstr) { - size_t length = 0; + static constexpr size_t len (const char *str) noexcept { + return !*str ? 0 : 1 + len (str + 1); + } - while (*cstr != kNullChar) { - length++; - cstr++; - } - return length; +public: + static constexpr uint32 fnv1a32 (const char *str, uint32 hash = 0x811c9dc5) { + return !*str ? hash : fnv1a32 (str + 1, (hash ^ static_cast (*str)) * 0x01000193); } public: @@ -81,7 +80,7 @@ private: public: constexpr StringRef () noexcept = default; - constexpr StringRef (const char *chars) : chars_ (chars), length_ (chars ? strLength (chars) : 0) + constexpr StringRef (const char *chars) : chars_ (chars), length_ (chars ? len (chars) : 0) { } constexpr StringRef (const char *chars, size_t length) : chars_ (chars), length_ (length) @@ -133,6 +132,10 @@ public: return *this == rhs; } + constexpr uint32 hash () const { + return fnv1a32 (chars ()); + } + public: int32 int_ () const { return atoi (chars ()); @@ -606,6 +609,10 @@ public: } public: + uint32 hash () const { + return str ().hash (); + } + bool contains (StringRef rhs) const { return str ().contains (rhs); } diff --git a/inc/config.h b/inc/config.h index d67304e..750a798 100644 --- a/inc/config.h +++ b/inc/config.h @@ -136,7 +136,7 @@ private: }; // hash the lang string, only the letters - uint32 hashLangString (const char *input); + uint32 hashLangString (StringRef str); public: diff --git a/src/botlib.cpp b/src/botlib.cpp index 4fe3a14..bf9dc36 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -1064,7 +1064,7 @@ void Bot::checkMsgQueue () { // prevent terrorists from buying on es maps if (game.mapIs (MapFlags::Escape) && m_team == Team::Terrorist) { - m_buyState = 6; + m_buyState = BuyState::Done;; } // prevent teams from buying on fun maps diff --git a/src/config.cpp b/src/config.cpp index ae368de..b5f58c5 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -764,23 +764,17 @@ const char *BotConfig::translate (StringRef input) { return input.chars (); // nothing found } -uint32 BotConfig::hashLangString (const char *input) { - auto str = reinterpret_cast (const_cast (input)); - uint32_t hash = 0; +uint32 BotConfig::hashLangString (StringRef str) { + auto test = [] (const char ch) { + return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); + }; + String res; - for (; *str; ++str) { - if (!isalnum (*str)) { + for (const auto &ch : str) { + if (!test (ch)) { continue; } - - hash += *str; - hash += (hash << 10); - hash ^= (hash >> 6); + res += ch; } - - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - - return hash; + return res.empty () ? 0 : res.hash (); } diff --git a/src/control.cpp b/src/control.cpp index 9282a9e..94dfafc 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -360,7 +360,9 @@ int BotControl::cmdNode () { if (strValue (cmd) == "help" && hasArg (cmd2) && commands.has (strValue (cmd2))) { auto &item = commands[strValue (cmd2)]; - msg ("Command: \"%s %s %s\"\nFormat: %s\nHelp: %s", m_args[root], m_args[alias], item.name, item.format, conf.translate (item.help)); + msg ("Command: \"%s %s %s\"", m_args[root], m_args[alias], item.name); + msg ("Format: %s", item.format); + msg ("Help: %s", conf.translate (item.help)); } else { for (auto &desc : descriptions) { @@ -1583,7 +1585,9 @@ bool BotControl::executeCommands () { } if ((hasSecondArg && aliasMatch (item.name, m_args[2], cmd)) || !hasSecondArg) { - msg ("Command: \"%s %s\"\nFormat: %s\nHelp: %s", prefix, cmd, item.format, conf.translate (item.help)); + msg ("Command: \"%s %s\"", prefix, cmd); + msg ("Format: %s", item.format); + msg ("Help: %s", conf.translate (item.help)); auto aliases = item.name.split ("/");