From ce01e652556a6f0ede7ef0dbd2c1d5842825dfb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Fri, 18 Sep 2026 14:13:31 +0200 Subject: [PATCH] Patch related to #6124 --- lib/core/settings.py | 2 +- sqlmap.py | 13 +++++++++++++ tests/test_jit_guard.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/core/settings.py b/lib/core/settings.py index 176d98252..db16a47e9 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from lib.core.enums import OS from thirdparty import six # sqlmap version (...) -VERSION = "1.10.9.14" +VERSION = "1.10.9.15" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) diff --git a/sqlmap.py b/sqlmap.py index d2eb8d96a..344d44e4b 100755 --- a/sqlmap.py +++ b/sqlmap.py @@ -12,6 +12,19 @@ try: sys.dont_write_bytecode = True + # Reference: https://github.com/python/cpython/issues/156319 - CPython's tier-2 optimizer can + # corrupt frame locals (raising exceptions the executed code cannot produce) whenever an active + # sys.monitoring tool (an attached debugger/profiler/coverage run) coincides with enough hot + # code. sqlmap never needs one attached during a scan, so silence any already-registered tool + # up front, before any hot code runs (name stays registered so the owning tool can still free it) + if hasattr(sys, "monitoring"): + for _ in range(6): # valid tool id range (Reference: https://docs.python.org/3/library/sys.monitoring.html) + try: + if sys.monitoring.get_tool(_) is not None: + sys.monitoring.set_events(_, sys.monitoring.events.NO_EVENTS) + except Exception: + pass + try: __import__("lib.utils.versioncheck") # this has to be the first non-standard import except ImportError: diff --git a/tests/test_jit_guard.py b/tests/test_jit_guard.py index 3a5fbde45..c56271de1 100644 --- a/tests/test_jit_guard.py +++ b/tests/test_jit_guard.py @@ -81,5 +81,38 @@ class TestJitGuard(unittest.TestCase): self.assertIn(PROMPT, out) +# Tool id 3 is unused by CPython's own well-known ids (DEBUGGER=0, COVERAGE=1, PROFILER=2, OPTIMIZER=5) +_TEST_TOOL_ID = 3 + +_MONITORING_DRIVER = """ +import sys +sys.path.insert(0, %r) +sys.monitoring.use_tool_id(%d, "test-tool") +sys.monitoring.set_events(%d, sys.monitoring.events.PY_START) +import sqlmap +print(sys.monitoring.get_tool(%d)) +print(sys.monitoring.get_events(%d)) +""" % (ROOT, _TEST_TOOL_ID, _TEST_TOOL_ID, _TEST_TOOL_ID, _TEST_TOOL_ID) + + +class TestMonitoringGuard(unittest.TestCase): + """ + The other half of the cpython#156319 mitigation: the tier-2 corruption needs BOTH the JIT and + an active sys.monitoring tool (debugger/profiler/coverage) at once. sqlmap has no legitimate + reason to run a scan with one attached, so it silences any already-registered tool's events as + the very first thing at import time (Reference: 'https://github.com/python/cpython/issues/156319'). + """ + + def test_active_tool_is_silenced_but_not_unregistered(self): + if not hasattr(sys, "monitoring"): + self.skipTest("interpreter has no sys.monitoring (needs 3.12+)") + + out = subprocess.check_output([sys.executable, "-c", _MONITORING_DRIVER], cwd=ROOT) + tool, events = out.decode("utf-8").strip().splitlines() + + self.assertEqual(tool, "test-tool") # still registered - its own owner can still free it + self.assertEqual(events, "0") # events cleared to NO_EVENTS, so nothing fires + + if __name__ == "__main__": unittest.main()