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.
|
||||
* 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
|
||||
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
import re
|
||||
import logging
|
||||
|
||||
log = logging.getLogger("SafeRe")
|
||||
|
||||
|
||||
|
||||
class UnsafePatternError(Exception):
|
||||
pass
|
||||
|
||||
max_cache_size = 1000
|
||||
cached_patterns = {}
|
||||
old_cached_patterns = {}
|
||||
|
||||
|
||||
def isSafePattern(pattern):
|
||||
|
@ -22,11 +28,35 @@ def isSafePattern(pattern):
|
|||
return True
|
||||
|
||||
|
||||
def match(pattern, *args, **kwargs):
|
||||
def compilePattern(pattern):
|
||||
global cached_patterns
|
||||
global old_cached_patterns
|
||||
|
||||
cached_pattern = cached_patterns.get(pattern)
|
||||
if cached_pattern:
|
||||
return cached_pattern.match(*args, **kwargs)
|
||||
else:
|
||||
if isSafePattern(pattern):
|
||||
cached_patterns[pattern] = re.compile(pattern)
|
||||
return cached_patterns[pattern].match(*args, **kwargs)
|
||||
return cached_pattern
|
||||
|
||||
cached_pattern = old_cached_patterns.get(pattern)
|
||||
if cached_pattern:
|
||||
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