diff --git a/data/txt/sha256sums.txt b/data/txt/sha256sums.txt
index 89807f23e..772e791c8 100644
--- a/data/txt/sha256sums.txt
+++ b/data/txt/sha256sums.txt
@@ -84,7 +84,7 @@ c8d467837c8567b61a11e2dfd75a2d8305a8b317041ee81eda6d0e47609dabb7 data/xml/paylo
0648264166455010921df1ec431e4c973809f37ef12cbfea75f95029222eb689 data/xml/payloads/stacked_queries.xml
379fc92f2dadd948f401e17490d8a8f03a1988d817323cbe1feff5fe87726079 data/xml/payloads/time_blind.xml
40a4878669f318568097719d07dc906a19b8520bc742be3583321fc1e8176089 data/xml/payloads/union_query.xml
-a6127cc68b62709149a0e58a314d9003865945018cc5a43d60afc3698d92c6e9 data/xml/queries.xml
+6eca98949c361bbcf5edd5e24dcf001dbaee5b37b244978df7e319cf48dac514 data/xml/queries.xml
127799739f9aeabca367027197f3c0240f141303bd7499928ccfa1443bf148c7 doc/ARCHITECTURE.md
0f5a9c84cb57809be8759f483c7d05f54847115e715521ac0ecf390c0aa68465 doc/AUTHORS
ce20a4b452f24a97fde7ec9ed816feee12ac148e1fde5f1722772cc866b12740 doc/CHANGELOG.md
@@ -166,9 +166,9 @@ a2bf70d7f87c3a4e0675c0bad54119a4e04efa6ea2730a8338d5aebcd995630e lib/controller
96463b969312bd4fd29452b5fc739f33e5a73f81fdc1ef80ac27debbe9926e42 lib/controller/controller.py
d69e84f1648cdb907f5d2dd454f03874a4613752b07867510145d51d84b3c56f lib/controller/handler.py
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/controller/__init__.py
-1276ff64ad145157d8c65ce08f3066b6db041d12f7d1eee590c06123c700b18d lib/core/agent.py
+9c5764c92ce536d1f0f96200359ee5ef1f37f9128769bf990cb77f1d1f8e17b1 lib/core/agent.py
c51c33501cc905586a9aaac93b06f2ac6f71628d032a7dc39fd0ef05d7ee3856 lib/core/bigarray.py
-5a8dcfc6c43927e4a132d34abf5d75193eaeb3feb0cb58d0ff5bdc059c876ba9 lib/core/common.py
+122767794156afa41b19baa706ad4c124eef6eaf73ed8fd208d8f634e97e82eb lib/core/common.py
8f1272487e1adfcc8c755a2f56f0c6d21eac5e685a73a9a159482f9dc9142bc5 lib/core/compat.py
742bce10b97034966021ec60c7ac294db4af4fe7893613d63172a02c29f009f8 lib/core/convert.py
c03dc585f89642cfd81b087ac2723e3e1bb3bfa8c60e6f5fe58ef3b0113ebfe6 lib/core/data.py
@@ -189,7 +189,7 @@ ccc4a717e887652b1fcce073d9409d9c59a3b28548c703a9e453d15845f90cd7 lib/core/patch
9bf174058f15d14e24e94f9aaf42df045119d3617c6c54bd2f3af79b462f331d lib/core/replication.py
0b8c38a01bb01f843d94a6c5f2075ee47520d0c4aa799cecea9c3e2c5a4a23a6 lib/core/revision.py
888daba83fd4a34e9503fe21f01fef4cc730e5cde871b1d40e15d4cbc847d56c lib/core/session.py
-d6572ecbd0d7a26839f5098d68cb02fb5b498c88f0d1c36928c5611a96f9d19a lib/core/settings.py
+c7a6dd94cf738716cc48f1daacdd402ddb0e78a6c9260233e319cde4f9054a60 lib/core/settings.py
c7804223319e18eb0b8e2cbf0a8b6896d1cefb7b0b1a2e9f1cf826a8a3b56750 lib/core/shell.py
a2e98a94b231432736d6b304fc75525c8b5fdb4768c418387c5b4c1a610dad64 lib/core/subprocessng.py
19f1e3c5e3ba703d28d510cd7a9ab8284d5fbe9df5ce7e77c86e5931571364b7 lib/core/target.py
@@ -212,7 +212,7 @@ c2f34e27578742e729c2fa9c1d4f0a0d8f8f7f4cf0fc14c62ec817a260c71dec lib/parse/site
369484a2999d29f49bf839a329d1686ed94f6ea27c695e027fe08c8da51f30a3 lib/request/basic.py
bc61bc944b81a7670884f82231033a6ac703324b34b071c9834886a92e249d0e lib/request/chunkedhandler.py
d4bb0869b03602a0c8f9e0e0fd217753f14ddadf848fc9f3c65a74d03feb9958 lib/request/comparison.py
-b9e2db44d265909792f6cc821ff910727b14aa2d5063c74b0f2ea6d40c4f3d9d lib/request/connect.py
+729e07a2ca6b1d83563e9c6dc5a884d1b664c1764be06776ea93bde305164f0c lib/request/connect.py
8e06682280fce062eef6174351bfebcb6040e19976acff9dc7b3699779783498 lib/request/direct.py
a6b37b436838caeb197fea858d0a39fadbff4736256e741b5fcec1f28fcf1ce0 lib/request/dns.py
92c81cc31ff4a396723242058fb2152c9e9745f8412d01ea74480b048a53af6c lib/request/httpshandler.py
@@ -587,7 +587,7 @@ c17544be5e945dc8c4fbb5c3b922da8eceec30b0fb239c32fb5f40e1660a197f tests/test_dat
b6d8a4bc9c46a332a2dc7b3cf862ea67e38b5c5701cfd8eb3556021f6b611416 tests/test_dialectdbms.py
e40a49cfa73c45b3c3c6d1d1d00738861e270cb7a07b28f5a5356f9c7c800cf2 tests/test_dialect.py
993a2d4d87c4fbaf261663b069629acc95ee4405aa0c42cf5a8f39649fdb0fff tests/test_dicts.py
-7f12466974394312dad3d98651ef8a50d1585bee0f8cd25da0b77b08c2047e46 tests/test_dns_engine.py
+ed5a0e453b811dc3dcc5ca28e14a9d7552aacaa7e316e1bca1b042dc5939e204 tests/test_dns_engine.py
703faac01f38224ba85bd0fc398d939ea034f1d7fd641cdc15da4f77ec049443 tests/test_dns_server.py
9cd5841349bc4db818658d12184929a96f7f279eff1f53ad18a54dbefbd6b276 tests/test_dump_jsonl.py
2bbe4b01f79992cfa8884651fc0a28dbd0e3abb0cbea9eb7eadf1f98ca3c3420 tests/test_encoding.py
diff --git a/data/xml/queries.xml b/data/xml/queries.xml
index 826743553..9cfbce4e8 100644
--- a/data/xml/queries.xml
+++ b/data/xml/queries.xml
@@ -203,6 +203,7 @@
+
diff --git a/lib/core/agent.py b/lib/core/agent.py
index 686eb43bb..ec781a43e 100644
--- a/lib/core/agent.py
+++ b/lib/core/agent.py
@@ -70,9 +70,9 @@ class Agent(object):
query = self.cleanupPayload(query)
if query.upper().startswith("AND "):
- query = re.sub(r"(?i)AND ", "SELECT ", query, 1)
+ query = re.sub(r"(?i)AND ", "SELECT ", query, count=1)
elif query.upper().startswith(" UNION ALL "):
- query = re.sub(r"(?i) UNION ALL ", "", query, 1)
+ query = re.sub(r"(?i) UNION ALL ", "", query, count=1)
elif query.startswith("; "):
query = query.replace("; ", "", 1)
@@ -1126,7 +1126,7 @@ class Agent(object):
original = query.split("SELECT ", 1)[1].split(" FROM", 1)[0]
for part in original.split(','):
if re.search(r"\b%s\b" % re.escape(field), part):
- _ = re.sub(r"SELECT.+?FROM", "SELECT %s AS z,row_number() over() AS y FROM" % part, query, 1)
+ _ = re.sub(r"SELECT.+?FROM", "SELECT %s AS z,row_number() over() AS y FROM" % part, query, count=1)
replacement = "SELECT x.z FROM (%s)x WHERE x.y-1=%d" % (_, num)
limitedQuery = replacement
break
diff --git a/lib/core/common.py b/lib/core/common.py
index 5b04c9589..a8eca14ad 100644
--- a/lib/core/common.py
+++ b/lib/core/common.py
@@ -2271,7 +2271,7 @@ def safeStringFormat(format_, params):
if match:
try:
_ = getUnicode(params[count % len(params)])
- retVal = re.sub(r"(\A|[^A-Za-z0-9])(%s)([^A-Za-z0-9]|\Z)", r"\g<1>%s\g<3>" % _.replace('\\', r'\\'), retVal, 1)
+ retVal = re.sub(r"(\A|[^A-Za-z0-9])(%s)([^A-Za-z0-9]|\Z)", r"\g<1>%s\g<3>" % _.replace('\\', r'\\'), retVal, count=1)
except re.error:
retVal = retVal.replace(match.group(0), match.group(0) % params[count % len(params)], 1)
count += 1
@@ -3884,6 +3884,13 @@ def openFile(filename, mode='r', encoding=UNICODE_ENCODING, errors="reversible",
if 'b' in mode:
buffering = 0
encoding = None
+ elif buffering == 1 and codecs_open is codecs.open:
+ # codecs.open() always opens the underlying file in binary mode, where line buffering
+ # (buffering=1) is unsupported: on Python 3.12+ it emits a benign RuntimeWarning and is
+ # silently downgraded to the default buffer size anyway. Request that default explicitly
+ # so the warning never reaches users (the >=3.14 _codecs_open shim handles buffering=1
+ # itself, preserving flush-on-newline, so this only adjusts the legacy codecs.open path).
+ buffering = -1
if filename == STDIN_PIPE_DASH:
if filename not in kb.cache.content:
diff --git a/lib/core/settings.py b/lib/core/settings.py
index 8a8e81bfe..c25f9e0f6 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.6.156"
+VERSION = "1.10.6.157"
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/lib/request/connect.py b/lib/request/connect.py
index daa2a66ee..40c42390b 100644
--- a/lib/request/connect.py
+++ b/lib/request/connect.py
@@ -1018,7 +1018,7 @@ class Connect(object):
if conn and getattr(conn, "redurl", None):
_ = _urllib.parse.urlsplit(conn.redurl)
_ = ("%s%s" % (_.path or "/", ("?%s" % _.query) if _.query else ""))
- requestMsg = re.sub(r"(\n[A-Z]+ ).+?( HTTP/\d)", r"\g<1>%s\g<2>" % getUnicode(_).replace("\\", "\\\\"), requestMsg, 1)
+ requestMsg = re.sub(r"(\n[A-Z]+ ).+?( HTTP/\d)", r"\g<1>%s\g<2>" % getUnicode(_).replace("\\", "\\\\"), requestMsg, count=1)
if kb.resendPostOnRedirect is False:
requestMsg = re.sub(r"(\[#\d+\]:\n)POST ", r"\g<1>GET ", requestMsg)
diff --git a/tests/test_dns_engine.py b/tests/test_dns_engine.py
index bce8bff6a..5eaf2c0a7 100644
--- a/tests/test_dns_engine.py
+++ b/tests/test_dns_engine.py
@@ -43,6 +43,7 @@ bootstrap()
from lib.core.agent import agent
from lib.core.common import Backend
from lib.core.data import conf, kb
+from lib.core.threads import getCurrentThreadData
from lib.core.enums import DBMS
from lib.core.exception import SqlmapNotVulnerableException
from lib.core.settings import DNS_BOUNDARIES_ALPHABET
@@ -89,7 +90,12 @@ class _DnsCase(unittest.TestCase):
def setUpClass(cls):
cls.server = _HighPortDNSServer()
cls.server.run()
+ # bounded wait: never spin indefinitely if the in-process server fails to bind/init
+ # (e.g. a taken port on CI) - fail loudly instead of hanging the whole suite
+ deadline = time.time() + 10
while not cls.server._initialized:
+ if time.time() > deadline:
+ raise RuntimeError("in-process DNS test server failed to initialize within 10s")
time.sleep(0.02)
@classmethod
@@ -107,6 +113,11 @@ class _DnsCase(unittest.TestCase):
self._saved_randomInt = dnstestmod.randomInt
self._saved_dnsServer = conf.get("dnsServer")
self._saved_hdbR, self._saved_hdbW = dnsmod.hashDBRetrieve, dnsmod.hashDBWrite
+ # the DNS exfil path prints its own "[INFO] retrieved: ..." progress straight to stdout
+ # via dataToStdout() (it bypasses the logger, so the suite's log-level silencing can't
+ # catch it); suppress it through sqlmap's own per-thread stdout gate so the run stays clean
+ self._saved_disableStdOut = getCurrentThreadData().disableStdOut
+ getCurrentThreadData().disableStdOut = True
for k, v in _CONF.items():
conf[k] = v
for k, v in _KB.items():
@@ -125,6 +136,7 @@ class _DnsCase(unittest.TestCase):
set_dbms(self.DBMS_NAME)
def tearDown(self):
+ getCurrentThreadData().disableStdOut = self._saved_disableStdOut
for k, v in self._saved_conf.items():
conf[k] = v
for k, v in self._saved_kb.items():