blob: 747c467b069de23e5693bc0be67569d73a8b35ea [file] [log] [blame]
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/feedback.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/feedback.cpp
index d22c29618897..08198d740a48 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/feedback.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/feedback.cpp
@@ -9,14 +9,6 @@
namespace zxcvbn {
-const Feedback DEFAULT_FEEDBACK = {
- "",
- {
- "Use a few words, avoid common phrases",
- "No need for symbols, digits, or uppercase letters",
- },
-};
-
static
optional::optional<Feedback> get_match_feedback(const Match & match, bool is_sole_match);
@@ -26,7 +18,15 @@ Feedback get_dictionary_match_feedback(const Match & match, bool is_sole_match);
Feedback get_feedback(score_t score,
const std::vector<Match> & sequence) {
// starting feedback
- if (!sequence.size()) return DEFAULT_FEEDBACK;
+ if (!sequence.size()) {
+ return {
+ "",
+ {
+ "Use a few words, avoid common phrases",
+ "No need for symbols, digits, or uppercase letters",
+ },
+ };
+ }
// no feedback if score is good or great.
if (score > 2) return {"", {}};
@@ -151,12 +151,11 @@ Feedback get_dictionary_match_feedback(const Match & match_, bool is_sole_match)
std::vector<std::string> suggestions;
auto & word = match_.token;
- if (std::regex_search(word, START_UPPER)) {
+ if (std::regex_search(word, START_UPPER())) {
suggestions.push_back("Capitalization doesn't help very much");
- }
- else if (std::regex_search(word, ALL_UPPER) and
- // XXX: UTF-8
- util::ascii_lower(word) == word) {
+ } else if (std::regex_search(word, ALL_UPPER()) and
+ // XXX: UTF-8
+ util::ascii_lower(word) == word) {
suggestions.push_back("All-uppercase is almost as easy to guess as all-lowercase");
}
@@ -171,4 +170,3 @@ Feedback get_dictionary_match_feedback(const Match & match_, bool is_sole_match)
}
}
-
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.cpp
index c14e02618ec2..6d43cd2dc20b 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.cpp
@@ -19,28 +19,41 @@
#include <utility>
#include <unordered_set>
+#include "base/no_destructor.h"
+
namespace zxcvbn {
// TODO: make this a constexpr
-extern const std::vector<std::pair<std::string, std::vector<std::string>>> L33T_TABLE = {
- {"a", {"4", "@"}},
- {"b", {"8"}},
- {"c", {"(", "{", "[", "<"}},
- {"e", {"3"}},
- {"g", {"6", "9"}},
- {"i", {"1", "!", "|"}},
- {"l", {"1", "|", "7"}},
- {"o", {"0"}},
- {"s", {"$", "5"}},
- {"t", {"+", "7"}},
- {"x", {"%"}},
- {"z", {"2"}},
-};
+const std::vector<std::pair<std::string, std::vector<std::string>>>&
+L33T_TABLE() {
+ static base::NoDestructor<
+ std::vector<std::pair<std::string, std::vector<std::string>>>>
+ leet_table({
+ {"a", {"4", "@"}},
+ {"b", {"8"}},
+ {"c", {"(", "{", "[", "<"}},
+ {"e", {"3"}},
+ {"g", {"6", "9"}},
+ {"i", {"1", "!", "|"}},
+ {"l", {"1", "|", "7"}},
+ {"o", {"0"}},
+ {"s", {"$", "5"}},
+ {"t", {"+", "7"}},
+ {"x", {"%"}},
+ {"z", {"2"}},
+ });
+
+ return *leet_table;
+}
// TODO: make this constexpr
-extern const std::vector<std::pair<RegexTag, std::regex>> REGEXEN = {
- {RegexTag::RECENT_YEAR, std::regex(R"(19\d\d|200\d|201\d)")},
-};
+const std::vector<std::pair<RegexTag, std::regex>>& REGEXEN() {
+ static base::NoDestructor<std::vector<std::pair<RegexTag, std::regex>>>
+ regexen({
+ {RegexTag::RECENT_YEAR, std::regex(R"(19\d\d|200\d|201\d)")},
+ });
+ return *regexen;
+}
const auto DATE_MAX_YEAR = 2050;
const auto DATE_MIN_YEAR = 1000;
@@ -115,19 +128,18 @@ std::vector<Match> omnimatch(const std::string & password,
std::cref(ranked_dict)));
std::vector<Match> matches;
- std::function<std::vector<Match>(const std::string &)> matchers[] = {
- std::bind(dictionary_match, std::placeholders::_1,
- std::cref(ranked_dictionaries)),
- std::bind(reverse_dictionary_match, std::placeholders::_1,
- std::cref(ranked_dictionaries)),
- std::bind(l33t_match, std::placeholders::_1,
- std::cref(ranked_dictionaries), std::cref(L33T_TABLE)),
- std::bind(spatial_match, std::placeholders::_1,
- std::cref(graphs())),
- repeat_match,
- sequence_match,
- std::bind(regex_match, std::placeholders::_1, std::cref(REGEXEN)),
- date_match,
+ std::function<std::vector<Match>(const std::string&)> matchers[] = {
+ std::bind(dictionary_match, std::placeholders::_1,
+ std::cref(ranked_dictionaries)),
+ std::bind(reverse_dictionary_match, std::placeholders::_1,
+ std::cref(ranked_dictionaries)),
+ std::bind(l33t_match, std::placeholders::_1,
+ std::cref(ranked_dictionaries), std::cref(L33T_TABLE())),
+ std::bind(spatial_match, std::placeholders::_1, std::cref(graphs())),
+ repeat_match,
+ sequence_match,
+ std::bind(regex_match, std::placeholders::_1, std::cref(REGEXEN())),
+ date_match,
};
for (const auto & matcher : matchers) {
auto ret = matcher(password);
@@ -344,12 +356,13 @@ std::vector<Match> spatial_match(const std::string & password,
return matches;
}
-const auto SHIFTED_RX = std::regex("[~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?]");
-
static
std::vector<Match> spatial_match_helper(const std::string & password,
const Graph & graph,
GraphTag graph_tag) {
+ const auto SHIFTED_RX =
+ std::regex("[~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?]");
+
std::vector<Match> matches;
if (!password.length()) return matches;
idx_t idx = 0;
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp
index 7ded5d89573f..ba73b909157c 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp
@@ -10,8 +10,8 @@
namespace zxcvbn {
-extern const std::vector<std::pair<std::string, std::vector<std::string>>> L33T_TABLE;
-extern const std::vector<std::pair<RegexTag, std::regex>> REGEXEN;
+const std::vector<std::pair<std::string, std::vector<std::string>>>& L33T_TABLE();
+const std::vector<std::pair<RegexTag, std::regex>>& REGEXEN();
std::vector<Match> dictionary_match(const std::string & password,
const RankedDicts & ranked_dictionaries);
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching_js_bindings.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching_js_bindings.cpp
index 1dfcb53bc42d..1664a27b277c 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching_js_bindings.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching_js_bindings.cpp
@@ -66,7 +66,7 @@ emscripten::val _dictionary_match(const std::wstring & wpassword,
std::vector<std::pair<std::string, std::vector<std::string>>> _store;
auto & ret2 = [&] () -> const std::vector<std::pair<std::string, std::vector<std::string>>> & {
if (l33t_table.isUndefined()) {
- return zxcvbn::L33T_TABLE;
+ return zxcvbn::L33T_TABLE();
}
else {
auto ret = val_converter<std::unordered_map<std::string, std::vector<std::string>>>::from(l33t_table);
@@ -198,7 +198,7 @@ emscripten::val repeat_match(const std::wstring & wpassword) {
static
emscripten::val regex_match(const std::wstring & wpassword) {
- return to_val(zxcvbn::regex_match(to_utf8(wpassword), zxcvbn::REGEXEN));
+ return to_val(zxcvbn::regex_match(to_utf8(wpassword), zxcvbn::REGEXEN()));
}
static
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.cpp
index 96c4c76d1e65..fe2a2ec8cb8b 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.cpp
@@ -9,6 +9,8 @@
#include <cmath>
+#include "base/no_destructor.h"
+
namespace std {
template<class T, class U>
@@ -27,6 +29,26 @@ const auto MIN_GUESSES_BEFORE_GROWING_SEQUENCE = static_cast<guesses_t>(10000);
const auto MIN_SUBMATCH_GUESSES_SINGLE_CHAR = static_cast<guesses_t>(10);
const auto MIN_SUBMATCH_GUESSES_MULTI_CHAR = static_cast<guesses_t>(50);
+const std::regex& START_UPPER() {
+ static base::NoDestructor<std::regex> start_upper(R"(^[A-Z][^A-Z]+$)");
+ return *start_upper;
+}
+
+const std::regex& END_UPPER() {
+ static base::NoDestructor<std::regex> end_upper(R"(^[^A-Z]+[A-Z]$)");
+ return *end_upper;
+}
+
+const std::regex& ALL_UPPER() {
+ static base::NoDestructor<std::regex> all_upper(R"(^[^a-z]+$)");
+ return *all_upper;
+}
+
+const std::regex& ALL_LOWER() {
+ static base::NoDestructor<std::regex> all_lower(R"(^[^A-Z]+$)");
+ return *all_lower;
+}
+
template<class Tret, class Tin>
Tret factorial(Tin n) {
// unoptimized, called only on small n
@@ -441,11 +463,12 @@ guesses_t dictionary_guesses(const Match & match) {
guesses_t uppercase_variations(const Match & match) {
auto & word = match.token;
- if (std::regex_match(word, ALL_LOWER) || !word.size()) return 1;
+ if (std::regex_match(word, ALL_LOWER()) || !word.size())
+ return 1;
// a capitalized word is the most common capitalization scheme,
// so it only doubles the search space (uncapitalized + capitalized).
// allcaps and end-capitalized are common enough too, underestimate as 2x factor to be safe.
- for (const auto & regex : {START_UPPER, END_UPPER, ALL_UPPER}) {
+ for (const auto& regex : {START_UPPER(), END_UPPER(), ALL_UPPER()}) {
if (std::regex_match(word, regex)) return 2;
}
// otherwise calculate the number of ways to capitalize U+L uppercase+lowercase letters
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp
index ec9fd22d8e18..1038ee34587c 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp
@@ -11,10 +11,10 @@
namespace zxcvbn {
-const auto START_UPPER = std::regex(R"(^[A-Z][^A-Z]+$)");
-const auto END_UPPER = std::regex(R"(^[^A-Z]+[A-Z]$)");
-const auto ALL_UPPER = std::regex(R"(^[^a-z]+$)");
-const auto ALL_LOWER = std::regex(R"(^[^A-Z]+$)");
+const std::regex& START_UPPER();
+const std::regex& END_UPPER();
+const std::regex& ALL_UPPER();
+const std::regex& ALL_LOWER();
const guesses_t MIN_YEAR_SPACE = 20;
const auto REFERENCE_YEAR = 2016;
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp
index 084d3cc0cd7c..107bce0af064 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp
@@ -8,6 +8,8 @@
#include <cassert>
+#include "base/no_destructor.h"
+
namespace zxcvbn {
namespace util {
@@ -32,7 +34,10 @@ std::string reverse_string(const std::string & in) {
return conv.to_bytes(ret);
}
-const std::codecvt_utf8<char32_t> char32_conv;
+const std::codecvt_utf8<char32_t>& char32_conv() {
+ static base::NoDestructor<std::codecvt_utf8<char32_t>> char32_conv;
+ return *char32_conv;
+}
bool utf8_valid(std::string::const_iterator start,
std::string::const_iterator end) {
@@ -46,8 +51,8 @@ bool utf8_valid(std::string::const_iterator start,
char32_t new_char;
char32_t *to_next;
- auto res = char32_conv.in(st, from, from_end, from_next,
- &new_char, &new_char + 1, to_next);
+ auto res = char32_conv().in(st, from, from_end, from_next, &new_char,
+ &new_char + 1, to_next);
if (!((res == std::codecvt_utf8<char32_t>::result::partial &&
from_next != from_end) ||
(res == std::codecvt_utf8<char32_t>::result::ok &&
@@ -67,7 +72,7 @@ template<class It>
It _utf8_iter(It start, It end) {
assert(start != end);
std::mbstate_t st;
- auto amt = char32_conv.length(st, &*start, &*end, 1);
+ auto amt = char32_conv().length(st, &*start, &*end, 1);
return start + amt;
}
@@ -110,8 +115,8 @@ std::pair<char32_t, It> _utf8_decode(It it, It end) {
const char *from = &*it;
const char *from_end = &*end;
const char *from_next;
- auto res = char32_conv.in(st, from, from_end, from_next,
- &new_char, &new_char + 1, to_next);
+ auto res = char32_conv().in(st, from, from_end, from_next, &new_char,
+ &new_char + 1, to_next);
assert((res == std::codecvt_utf8<char32_t>::result::partial &&
from_next != from_end) ||
(res == std::codecvt_utf8<char32_t>::result::ok &&