mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-09-24 20:20:37 +00:00
fix: bound plain-text runs in parse_prompt_attention regex (#1919)
This commit is contained in:
parent
9a977388a8
commit
4a7da26b73
@ -821,7 +821,11 @@ std::vector<std::pair<std::string, float>> parse_prompt_attention(const std::str
|
|||||||
float round_bracket_multiplier = 1.1f;
|
float round_bracket_multiplier = 1.1f;
|
||||||
float square_bracket_multiplier = 1 / 1.1f;
|
float square_bracket_multiplier = 1 / 1.1f;
|
||||||
|
|
||||||
std::regex re_attention(R"(\\\(|\\\)|\\\[|\\\]|\\\\|\\|\(|\[|:([+-]?[.\d]+)\)|\)|\]|\bBREAK\b|[^\\()\[\]:B]+|:|\bB)");
|
// libstdc++ std::regex recurses per matched character, so unbounded runs
|
||||||
|
// overflow the stack. Split runs are merged back below.
|
||||||
|
const int max_plain_text_run = 1024;
|
||||||
|
std::regex re_attention(R"(\\\(|\\\)|\\\[|\\\]|\\\\|\\|\(|\[|\)|\]|\bBREAK\b|[^\\()\[\]:B]{1,)" +
|
||||||
|
std::to_string(max_plain_text_run) + R"(}|:|\bB)");
|
||||||
std::regex re_break(R"(\s*\bBREAK\b\s*)");
|
std::regex re_break(R"(\s*\bBREAK\b\s*)");
|
||||||
|
|
||||||
auto multiply_range = [&](int start_position, float multiplier) {
|
auto multiply_range = [&](int start_position, float multiplier) {
|
||||||
@ -830,22 +834,55 @@ std::vector<std::pair<std::string, float>> parse_prompt_attention(const std::str
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Kept out of the regex: bounding the repetition rejects valid long weights,
|
||||||
|
// leaving it unbounded overflows the stack.
|
||||||
|
auto lex_weight = [](const std::string& s, float& value) -> size_t {
|
||||||
|
size_t end = 0;
|
||||||
|
if (end < s.size() && (s[end] == '+' || s[end] == '-')) {
|
||||||
|
++end;
|
||||||
|
}
|
||||||
|
while (end < s.size() && (std::isdigit((unsigned char)s[end]) || s[end] == '.')) {
|
||||||
|
++end;
|
||||||
|
}
|
||||||
|
if (end >= s.size() || s[end] != ')') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::string number = s.substr(0, end);
|
||||||
|
char* number_end = nullptr;
|
||||||
|
float parsed = std::strtof(number.c_str(), &number_end);
|
||||||
|
const char* expected = number.c_str() + number.size();
|
||||||
|
// Without this ".", "+." and "1.2.3" would silently become weights.
|
||||||
|
if (number.empty() || number_end != expected || !std::isfinite(parsed)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
value = parsed;
|
||||||
|
return end + 1;
|
||||||
|
};
|
||||||
|
|
||||||
std::smatch m, m2;
|
std::smatch m, m2;
|
||||||
std::string remaining_text = text;
|
std::string remaining_text = text;
|
||||||
|
|
||||||
while (std::regex_search(remaining_text, m, re_attention)) {
|
while (std::regex_search(remaining_text, m, re_attention)) {
|
||||||
std::string text = m[0];
|
std::string text = m[0];
|
||||||
std::string weight = m[1];
|
std::string suffix = m.suffix();
|
||||||
|
|
||||||
|
if (text == ":") {
|
||||||
|
float weight_value = 1.0f;
|
||||||
|
size_t weight_length = lex_weight(suffix, weight_value);
|
||||||
|
if (weight_length > 0) {
|
||||||
|
if (!round_brackets.empty()) {
|
||||||
|
multiply_range(round_brackets.back(), weight_value);
|
||||||
|
round_brackets.pop_back();
|
||||||
|
}
|
||||||
|
remaining_text = suffix.substr(weight_length);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (text == "(") {
|
if (text == "(") {
|
||||||
round_brackets.push_back((int)res.size());
|
round_brackets.push_back((int)res.size());
|
||||||
} else if (text == "[") {
|
} else if (text == "[") {
|
||||||
square_brackets.push_back((int)res.size());
|
square_brackets.push_back((int)res.size());
|
||||||
} else if (!weight.empty()) {
|
|
||||||
if (!round_brackets.empty()) {
|
|
||||||
multiply_range(round_brackets.back(), std::stof(weight));
|
|
||||||
round_brackets.pop_back();
|
|
||||||
}
|
|
||||||
} else if (text == ")" && !round_brackets.empty()) {
|
} else if (text == ")" && !round_brackets.empty()) {
|
||||||
multiply_range(round_brackets.back(), round_bracket_multiplier);
|
multiply_range(round_brackets.back(), round_bracket_multiplier);
|
||||||
round_brackets.pop_back();
|
round_brackets.pop_back();
|
||||||
@ -860,7 +897,7 @@ std::vector<std::pair<std::string, float>> parse_prompt_attention(const std::str
|
|||||||
res.push_back({text, 1.0f});
|
res.push_back({text, 1.0f});
|
||||||
}
|
}
|
||||||
|
|
||||||
remaining_text = m.suffix();
|
remaining_text = suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int pos : round_brackets) {
|
for (int pos : round_brackets) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user