Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Re-apply: Move glob_to_regex and re_word_boundary to matrix-python-co…
Browse files Browse the repository at this point in the history
…mmon #11505 (#11687)

Co-authored-by: Sean Quah <seanq@element.io>
  • Loading branch information
reivilibre and Sean Quah authored Jan 5, 2022
1 parent 84d790a commit 84bfe47
Show file tree
Hide file tree
Showing 9 changed files with 14 additions and 123 deletions.
1 change: 1 addition & 0 deletions changelog.d/11505.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Move `glob_to_regex` and `re_word_boundary` to `matrix-python-common`.
1 change: 1 addition & 0 deletions changelog.d/11687.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Move `glob_to_regex` and `re_word_boundary` to `matrix-python-common`.
3 changes: 2 additions & 1 deletion synapse/config/room_directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@

from typing import List

from matrix_common.regex import glob_to_regex

from synapse.types import JsonDict
from synapse.util import glob_to_regex

from ._base import Config, ConfigError

Expand Down
3 changes: 2 additions & 1 deletion synapse/config/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
import os
from typing import List, Optional, Pattern

from matrix_common.regex import glob_to_regex

from OpenSSL import SSL, crypto
from twisted.internet._sslverify import Certificate, trustRootFromCertificates

from synapse.config._base import Config, ConfigError
from synapse.util import glob_to_regex

logger = logging.getLogger(__name__)

Expand Down
3 changes: 2 additions & 1 deletion synapse/federation/federation_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
Union,
)

from matrix_common.regex import glob_to_regex
from prometheus_client import Counter, Gauge, Histogram

from twisted.internet.abstract import isIPAddress
Expand Down Expand Up @@ -65,7 +66,7 @@
)
from synapse.storage.databases.main.lock import Lock
from synapse.types import JsonDict, get_domain_from_id
from synapse.util import glob_to_regex, json_decoder, unwrapFirstError
from synapse.util import json_decoder, unwrapFirstError
from synapse.util.async_helpers import Linearizer, concurrently_execute, gather_results
from synapse.util.caches.response_cache import ResponseCache
from synapse.util.stringutils import parse_server_name
Expand Down
7 changes: 4 additions & 3 deletions synapse/push/push_rule_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
import re
from typing import Any, Dict, List, Optional, Pattern, Tuple, Union

from matrix_common.regex import glob_to_regex, to_word_pattern

from synapse.events import EventBase
from synapse.types import JsonDict, UserID
from synapse.util import glob_to_regex, re_word_boundary
from synapse.util.caches.lrucache import LruCache

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -184,7 +185,7 @@ def _contains_display_name(self, display_name: Optional[str]) -> bool:
r = regex_cache.get((display_name, False, True), None)
if not r:
r1 = re.escape(display_name)
r1 = re_word_boundary(r1)
r1 = to_word_pattern(r1)
r = re.compile(r1, flags=re.IGNORECASE)
regex_cache[(display_name, False, True)] = r

Expand Down Expand Up @@ -213,7 +214,7 @@ def _glob_matches(glob: str, value: str, word_boundary: bool = False) -> bool:
try:
r = regex_cache.get((glob, True, word_boundary), None)
if not r:
r = glob_to_regex(glob, word_boundary)
r = glob_to_regex(glob, word_boundary=word_boundary)
regex_cache[(glob, True, word_boundary)] = r
return bool(r.search(value))
except re.error:
Expand Down
1 change: 1 addition & 0 deletions synapse/python_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
# with the latest security patches.
"cryptography>=3.4.7",
"ijson>=3.1",
"matrix-common==1.0.0",
]

CONDITIONAL_REQUIREMENTS = {
Expand Down
59 changes: 1 addition & 58 deletions synapse/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@

import json
import logging
import re
import typing
from typing import Any, Callable, Dict, Generator, Optional, Pattern
from typing import Any, Callable, Dict, Generator, Optional

import attr
from frozendict import frozendict
Expand All @@ -35,9 +34,6 @@
logger = logging.getLogger(__name__)


_WILDCARD_RUN = re.compile(r"([\?\*]+)")


def _reject_invalid_json(val: Any) -> None:
"""Do not allow Infinity, -Infinity, or NaN values in JSON."""
raise ValueError("Invalid JSON value: '%s'" % val)
Expand Down Expand Up @@ -185,56 +181,3 @@ def log_failure(
if not consumeErrors:
return failure
return None


def glob_to_regex(glob: str, word_boundary: bool = False) -> Pattern:
"""Converts a glob to a compiled regex object.
Args:
glob: pattern to match
word_boundary: If True, the pattern will be allowed to match at word boundaries
anywhere in the string. Otherwise, the pattern is anchored at the start and
end of the string.
Returns:
compiled regex pattern
"""

# Patterns with wildcards must be simplified to avoid performance cliffs
# - The glob `?**?**?` is equivalent to the glob `???*`
# - The glob `???*` is equivalent to the regex `.{3,}`
chunks = []
for chunk in _WILDCARD_RUN.split(glob):
# No wildcards? re.escape()
if not _WILDCARD_RUN.match(chunk):
chunks.append(re.escape(chunk))
continue

# Wildcards? Simplify.
qmarks = chunk.count("?")
if "*" in chunk:
chunks.append(".{%d,}" % qmarks)
else:
chunks.append(".{%d}" % qmarks)

res = "".join(chunks)

if word_boundary:
res = re_word_boundary(res)
else:
# \A anchors at start of string, \Z at end of string
res = r"\A" + res + r"\Z"

return re.compile(res, re.IGNORECASE)


def re_word_boundary(r: str) -> str:
"""
Adds word boundary characters to the start and end of an
expression to require that the match occur as a whole word,
but do so respecting the fact that strings starting or ending
with non-word characters will change word boundaries.
"""
# we can't use \b as it chokes on unicode. however \W seems to be okay
# as shorthand for [^0-9A-Za-z_].
return r"(^|\W)%s(\W|$)" % (r,)
59 changes: 0 additions & 59 deletions tests/util/test_glob_to_regex.py

This file was deleted.

0 comments on commit 84bfe47

Please sign in to comment.