Fix possible infinite growing of the SafeRe
regexp cache by limiting the cache size
This commit is contained in:
parent
d2b65c550c
commit
769a2c08dd
2 changed files with 37 additions and 6 deletions
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
* Implemented the log level overriding for separate modules for easier debugging.
|
* Implemented the log level overriding for separate modules for easier debugging.
|
||||||
* Make the site block check implemented in `ContentFilter` usable from plugins and core modules via `SiteManager.isAddressBlocked()`.
|
* Make the site block check implemented in `ContentFilter` usable from plugins and core modules via `SiteManager.isAddressBlocked()`.
|
||||||
|
* Fixed possible infinite growing of the `SafeRe` regexp cache by limiting the cache size.
|
||||||
|
|
||||||
## Docker Image
|
## Docker Image
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
import re
|
import re
|
||||||
|
import logging
|
||||||
|
|
||||||
|
log = logging.getLogger("SafeRe")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UnsafePatternError(Exception):
|
class UnsafePatternError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
max_cache_size = 1000
|
||||||
cached_patterns = {}
|
cached_patterns = {}
|
||||||
|
old_cached_patterns = {}
|
||||||
|
|
||||||
|
|
||||||
def isSafePattern(pattern):
|
def isSafePattern(pattern):
|
||||||
|
@ -22,11 +28,35 @@ def isSafePattern(pattern):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def match(pattern, *args, **kwargs):
|
def compilePattern(pattern):
|
||||||
|
global cached_patterns
|
||||||
|
global old_cached_patterns
|
||||||
|
|
||||||
cached_pattern = cached_patterns.get(pattern)
|
cached_pattern = cached_patterns.get(pattern)
|
||||||
if cached_pattern:
|
if cached_pattern:
|
||||||
return cached_pattern.match(*args, **kwargs)
|
return cached_pattern
|
||||||
else:
|
|
||||||
if isSafePattern(pattern):
|
cached_pattern = old_cached_patterns.get(pattern)
|
||||||
cached_patterns[pattern] = re.compile(pattern)
|
if cached_pattern:
|
||||||
return cached_patterns[pattern].match(*args, **kwargs)
|
del old_cached_patterns[pattern]
|
||||||
|
cached_patterns[pattern] = cached_pattern
|
||||||
|
return cached_pattern
|
||||||
|
|
||||||
|
if isSafePattern(pattern):
|
||||||
|
cached_pattern = re.compile(pattern)
|
||||||
|
cached_patterns[pattern] = cached_pattern
|
||||||
|
log.debug("Compiled new pattern: %s" % pattern)
|
||||||
|
log.debug("Cache size: %d + %d" % (len(cached_patterns), len(old_cached_patterns)))
|
||||||
|
|
||||||
|
if len(cached_patterns) > max_cache_size:
|
||||||
|
old_cached_patterns = cached_patterns
|
||||||
|
cached_patterns = {}
|
||||||
|
log.debug("Size limit reached. Rotating cache.")
|
||||||
|
log.debug("Cache size: %d + %d" % (len(cached_patterns), len(old_cached_patterns)))
|
||||||
|
|
||||||
|
return cached_pattern
|
||||||
|
|
||||||
|
|
||||||
|
def match(pattern, *args, **kwargs):
|
||||||
|
cached_pattern = compilePattern(pattern)
|
||||||
|
return cached_pattern.match(*args, **kwargs)
|
||||||
|
|
Loading…
Reference in a new issue