From d5b66533e7829654f6fb343abbaaeab988dbfde8 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 24 Aug 2026 18:56:39 -0400 Subject: [PATCH] refac --- backend/open_webui/tools/knowledge_fs.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/backend/open_webui/tools/knowledge_fs.py b/backend/open_webui/tools/knowledge_fs.py index e7b2e7ee51..833f2fed89 100644 --- a/backend/open_webui/tools/knowledge_fs.py +++ b/backend/open_webui/tools/knowledge_fs.py @@ -32,6 +32,9 @@ DEFAULT_TAIL_LINES = 10 # Matching time allowed per tool call. Backtracking cost is exponential in the length of the # matched text, so capping the pattern or the line does not bound it. MATCH_BUDGET_SECONDS = 2.0 +MAX_REGEX_QUANTIFIER_COUNT = 2_000 +MAX_REGEX_QUANTIFIER_EXPANSION = 100_000 +_COUNTED_QUANTIFIER_RE = re.compile(r'(? str: return pattern.replace('\\|', '|').replace('\|', '|') +def validate_regex_quantifiers(pattern: str) -> str | None: + """Reject counted quantifiers that make regex compilation expand too much.""" + quantifier_expansion = 1 + for quantifier in _COUNTED_QUANTIFIER_RE.finditer(pattern): + count_text = quantifier.group(1) + count = int(count_text) if len(count_text) <= 6 else MAX_REGEX_QUANTIFIER_COUNT + 1 + if count > MAX_REGEX_QUANTIFIER_COUNT: + return f'Regex quantifier counts over {MAX_REGEX_QUANTIFIER_COUNT:g} are not supported' + + # ponytail: conservative expansion catches nested quantifier bombs without mirroring regex syntax. + quantifier_expansion *= max(count, 1) + if quantifier_expansion > MAX_REGEX_QUANTIFIER_EXPANSION: + return 'Regex quantifiers expand too much, lower the counts' + + return None + + def build_matcher(pattern: str, case_insensitive: bool = False, use_regex: bool = False) -> tuple: """Build a matcher function. Returns (match_fn, error_str_or_None).""" if not use_regex and is_regex_pattern(pattern): @@ -91,6 +111,9 @@ def build_matcher(pattern: str, case_insensitive: bool = False, use_regex: bool if use_regex: normalized = normalize_regex(pattern) + quantifier_error = validate_regex_quantifiers(normalized) + if quantifier_error: + return None, quantifier_error try: re_flags = regex.IGNORECASE if case_insensitive else 0 compiled = regex.compile(normalized, re_flags)