SIGN IN SIGN UP
sqlmapproject / sqlmap UNCLAIMED

Automatic SQL injection and database takeover tool

36983 0 0 Python
2019-05-08 12:47:52 +02:00
#!/usr/bin/env python
"""
2026-01-01 19:12:07 +01:00
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
2017-10-11 14:50:46 +02:00
See the file 'LICENSE' for copying permission
"""
import functools
2019-01-29 23:44:58 +01:00
import threading
2017-12-24 23:54:43 +01:00
2019-06-04 14:44:06 +02:00
from lib.core.datatype import LRUDict
2019-01-29 23:44:58 +01:00
from lib.core.settings import MAX_CACHE_ITEMS
from lib.core.threads import getCurrentThreadData
2019-07-30 20:28:56 +02:00
_cache = {}
2025-07-09 22:07:24 +02:00
_method_locks = {}
2019-01-29 23:44:58 +01:00
2019-07-30 20:28:56 +02:00
def cachedmethod(f):
"""
Method with a cached content
2019-05-06 14:41:35 +02:00
>>> __ = cachedmethod(lambda _: _)
>>> __(1)
1
2021-02-08 11:46:19 +01:00
>>> __(1)
1
2019-05-06 14:41:35 +02:00
>>> __ = cachedmethod(lambda *args, **kwargs: args[0])
>>> __(2)
2
2020-01-28 09:42:00 +01:00
>>> __ = cachedmethod(lambda *args, **kwargs: next(iter(kwargs.values())))
2019-05-06 14:41:35 +02:00
>>> __(foobar=3)
3
Reference: http://code.activestate.com/recipes/325205-cache-decorator-in-python-24/
"""
2013-01-30 10:38:11 +01:00
2019-07-30 20:28:56 +02:00
_cache[f] = LRUDict(capacity=MAX_CACHE_ITEMS)
2025-07-09 22:07:24 +02:00
_method_locks[f] = threading.RLock()
2019-07-30 20:28:56 +02:00
2026-01-30 18:35:19 +01:00
def _freeze(val):
if isinstance(val, (list, set, tuple)):
return tuple(_freeze(x) for x in val)
if isinstance(val, dict):
return tuple(sorted((k, _freeze(v)) for k, v in val.items()))
return val
@functools.wraps(f)
2019-07-30 20:28:56 +02:00
def _f(*args, **kwargs):
2026-01-30 18:35:19 +01:00
lock, cache = _method_locks[f], _cache[f]
2019-02-09 23:18:08 +01:00
try:
2025-12-30 13:04:13 +01:00
if kwargs:
2026-01-30 18:35:19 +01:00
key = (args, frozenset(kwargs.items()))
2025-12-30 13:04:13 +01:00
else:
2026-01-30 18:35:19 +01:00
key = args
2025-12-30 13:04:13 +01:00
2026-01-30 18:35:19 +01:00
with lock:
if key in cache:
return cache[key]
2025-12-28 01:33:15 +01:00
2026-01-30 18:35:19 +01:00
except TypeError:
# Note: fallback (slowpath(
if kwargs:
key = (_freeze(args), _freeze(kwargs))
else:
key = _freeze(args)
with lock:
if key in cache:
return cache[key]
2025-12-28 01:33:15 +01:00
2025-12-30 13:04:13 +01:00
result = f(*args, **kwargs)
2025-12-28 01:33:15 +01:00
2025-12-30 13:04:13 +01:00
with lock:
cache[key] = result
2019-02-09 23:18:08 +01:00
return result
2013-01-30 10:38:11 +01:00
2019-07-30 20:28:56 +02:00
return _f
def stackedmethod(f):
"""
Method using pushValue/popValue functions (fallback function for stack realignment)
2019-05-06 14:41:35 +02:00
>>> threadData = getCurrentThreadData()
>>> original = len(threadData.valueStack)
>>> __ = stackedmethod(lambda _: threadData.valueStack.append(_))
>>> __(1)
>>> len(threadData.valueStack) == original
True
"""
@functools.wraps(f)
def _(*args, **kwargs):
threadData = getCurrentThreadData()
originalLevel = len(threadData.valueStack)
try:
result = f(*args, **kwargs)
finally:
if len(threadData.valueStack) > originalLevel:
2026-01-07 17:34:26 +01:00
del threadData.valueStack[originalLevel:]
return result
2018-06-09 23:38:00 +02:00
return _
def lockedmethod(f):
2026-01-09 17:01:00 +01:00
"""
Decorates a function or method with a reentrant lock (only one thread can execute the function at a time)
>>> @lockedmethod
... def recursive_count(n):
... if n <= 0: return 0
... return n + recursive_count(n - 1)
>>> recursive_count(5)
15
"""
2025-07-09 20:53:58 +02:00
lock = threading.RLock()
@functools.wraps(f)
def _(*args, **kwargs):
2025-07-09 20:53:58 +02:00
with lock:
result = f(*args, **kwargs)
return result
return _