From fd7eaf107bf786e180e4caae1a9fdc8da8902102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Mon, 29 Jun 2026 23:36:02 +0200 Subject: [PATCH] Minor fix --- .github/workflows/tests.yml | 16 ++++++++++------ data/txt/sha256sums.txt | 10 +++++----- lib/core/settings.py | 2 +- lib/core/testing.py | 14 ++++++++++++++ tests/_testutils.py | 9 +++++++++ tests/test_hash_crack.py | 11 +++++++++++ tests/test_xpath.py | 2 ++ 7 files changed, 52 insertions(+), 12 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5fabed9c2..367bec214 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -93,13 +93,19 @@ jobs: - name: Basic import test run: python -c "import sqlmap; import sqlmapapi" + - name: Install optional test deps (lxml, jinja2) + # lxml has no PyPy-2.7 wheel and 5.x is Py3-only, so it cannot be pip-installed there. The + # tests that use it (test_xpath's real-XPath checks, and the --xpath/--ssti vuln-test + # endpoints) skip themselves when the engine is unavailable, so these deps are only needed + # on the Py3 jobs. + if: matrix.python-version != 'pypy-2.7' + run: python -m pip install -q lxml jinja2 + - name: Unit tests # -B: do not write .pyc files. On Python 2 / PyPy a cached .pyc makes a module's __file__ # point at the .pyc, which would make the later --smoke getFileType(__file__) doctest see # 'binary' instead of 'text'. Keeping this step byte-compile-free leaves --smoke clean. - run: | - python -m pip install -q lxml jinja2 - python -B -m unittest discover -s tests -p "test_*.py" + run: python -B -m unittest discover -s tests -p "test_*.py" - name: Coverage if: matrix.python-version != 'pypy-2.7' @@ -110,9 +116,7 @@ jobs: python -m coverage report --fail-under=50 - name: Smoke test - run: | - python -m pip install -q lxml jinja2 - python sqlmap.py --smoke-test + run: python sqlmap.py --smoke-test - name: Vuln test run: python sqlmap.py --vuln-test diff --git a/data/txt/sha256sums.txt b/data/txt/sha256sums.txt index 4890dd949..c7b61b8d8 100644 --- a/data/txt/sha256sums.txt +++ b/data/txt/sha256sums.txt @@ -189,11 +189,11 @@ e033b20a0f7821797a10f4bf4235723f38c7db551c611fbb713faa621b123c4a lib/core/optio 9bf174058f15d14e24e94f9aaf42df045119d3617c6c54bd2f3af79b462f331d lib/core/replication.py 0b8c38a01bb01f843d94a6c5f2075ee47520d0c4aa799cecea9c3e2c5a4a23a6 lib/core/revision.py 888daba83fd4a34e9503fe21f01fef4cc730e5cde871b1d40e15d4cbc847d56c lib/core/session.py -ccc5d5c67d6e62cf9232a57ba0fc6f4ce4bcd44f6f836934b2e35f4dcd08cd0c lib/core/settings.py +63d268179251bfbf231a5f4d5242e628a465be88a37e6e58accac950aa0b2f74 lib/core/settings.py c7804223319e18eb0b8e2cbf0a8b6896d1cefb7b0b1a2e9f1cf826a8a3b56750 lib/core/shell.py a2e98a94b231432736d6b304fc75525c8b5fdb4768c418387c5b4c1a610dad64 lib/core/subprocessng.py 19f1e3c5e3ba703d28d510cd7a9ab8284d5fbe9df5ce7e77c86e5931571364b7 lib/core/target.py -4056457dd8502ec367ec4633a33856561f562778f862fedc1372531bb2f58671 lib/core/testing.py +e2c6321ffc5a384dcf2115248053a731dfca43cc62067d661012f558eb6ad87e lib/core/testing.py 95656c44bab1771f4808030dd6a17eae5b129cb1234443f00b19695c7b712b86 lib/core/threads.py b9aacb840310173202f79c2ba125b0243003ee6b44c92eca50424f2bdfc83c02 lib/core/unescaper.py 53e396902cb2546eaa09e77073fcba8be8827ee9ce055cfc899e81b0e6ad4d6d lib/core/update.py @@ -618,7 +618,7 @@ bb6991260a994fcbe79e05febaa34affd5631d02299fbc626820addd5f6ea4f4 tests/test_err f1f38f8b8ca667caadcb027d1a20eb895be4ef0935511114db235e66903bb463 tests/test_graphql.py 50b71422ee91b9a4864f4d5ce6c9bdf169dc5f57ed1db05c152eb010c282136b tests/test_gui_helpers.py 92648f2fe81e22c5726b198bbbda14961cd4d3294a0d9139dcea808b324142ac tests/test_har.py -70919c6ee8fbb3d619873489c819fa37d9035beb2e9b658cc5aa531d86a40380 tests/test_hash_crack.py +cc7677bc6c568c395112c1aa7d01e1d664e4d5940c86cb4d44987172864bae6f tests/test_hash_crack.py 0336c875dd2b6554bff6eafd746229e38c69ca8070cd933d45cf27c82ef3e05f tests/test_hashdb.py c04e8358fb6df45f69f2f26435c971acde280535bf304e84d30cf2681158c6a7 tests/test_hash.py d539d0ae758b5bb91e314ab82ab4fe03d6fb2f8b377d16aefa6d7d1d77a7d5a9 tests/test_identifiers_output.py @@ -655,11 +655,11 @@ f49bcce1df533ffa1acfd02af43faf6687b21eebda9362ceb1e5871b8cb37fd4 tests/test_thr 48b0ae4abe0fdde8ce4975c5cbf4c3514a2815021cb2e3a490a189bea5edfe78 tests/test_unpickle_security.py 4b646f513c6da1e33200184ed6eabe0aa345eb2e2a19598dc123e191168591bf tests/test_urls.py eca021208e388b4d14c53f1e9f8a6e7d685e54ba572fb2a8487e6b620a20bcb5 tests/test_users_enum.py -23ffd75b5aec33066e6d6aad01ab2c9c1b12ee20c1a0990f8f1be81f1ad16161 tests/_testutils.py +045f05f958100adc883b3f56613c5f8002dd19d0752225397a1f771775cb2779 tests/_testutils.py 2364db35025a53ea4e5a0a80c034997642785f7e6d1566d0d0f1db959fe3c82e tests/test_utils.py 93ef9944effc62d4f744c57bd643137c90fd92205c6a6cbe891e0e99efb80a7f tests/test_wafbypass.py 81bb6d7449f224fa337734ae361c1a340bf9a51768a854d6a1a6e718ed1263ca tests/test_wordlist.py -9c1c23a83408e6012e019e82ffb53e25e317054d1b28ca61a2c4fe830a472fcf tests/test_xpath.py +2698060e7f001e054e345512ce95be458d9902b913afa769398b53145475738a tests/test_xpath.py 55eaefc664bd8598329d535370612351ec8443c52465f0a37172ea46a97c458a thirdparty/ansistrm/ansistrm.py e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 thirdparty/ansistrm/__init__.py f597b49ef445bfbfb8f98d1f1a08dcfe4810de5769c0abfab7cdce4eebbfcae7 thirdparty/beautifulsoup/beautifulsoup.py diff --git a/lib/core/settings.py b/lib/core/settings.py index 6fb116bb3..0d75036cb 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.192" +VERSION = "1.10.6.193" 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/core/testing.py b/lib/core/testing.py index 714304aca..7a33b5ff4 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -100,6 +100,20 @@ def vulnTest(): ("--purge -v 3", ("~ERROR", "~CRITICAL", "deleting the whole directory tree")), ) + # The vulnserver's XPath endpoint renders with lxml and its SSTI endpoint with jinja2; where those + # optional third-party engines are not importable (e.g. PyPy 2.7, which has no lxml wheel), skip + # just those entries instead of failing the whole run - the rest of the suite is unaffected. + try: + import lxml # noqa + except ImportError: + TESTS = tuple(_ for _ in TESTS if "--xpath" not in _[0]) + logger.warning("skipping the XPath vuln-test entry ('lxml' not available)") + try: + import jinja2 # noqa + except ImportError: + TESTS = tuple(_ for _ in TESTS if "--ssti" not in _[0]) + logger.warning("skipping the SSTI vuln-test entry ('jinja2' not available)") + retVal = True count = 0 cleanups = [] diff --git a/tests/_testutils.py b/tests/_testutils.py index 7ec9a4e3b..781f54749 100644 --- a/tests/_testutils.py +++ b/tests/_testutils.py @@ -73,6 +73,15 @@ def bootstrap(): import logging logging.getLogger("sqlmapLog").setLevel(logging.CRITICAL + 1) + # Some console output bypasses the logger entirely and goes straight through dataToStdout(): + # the \r-progress lines ("[INFO] retrieved: ...", "[INFO] cracked password ..."), and the echo + # of batch-auto-answered readInput() prompts (the fingerprint-mismatch prompt, the LIKE/exact + # and common-wordlist choices, ...). dataToStdout() only writes forced output or when + # kb.wizardMode is False, and readInput() echoes with forceOutput=not kb.wizardMode - so setting + # wizardMode keeps the unittest report to just dots. wizardMode is read ONLY by dataToStdout/ + # readInput (plus the interactive wizard flow, unused here), so this has no effect on results. + kb.wizardMode = True + sys.argv = _orig_argv # restore so unittest's arg parsing works _BOOTSTRAPPED = True diff --git a/tests/test_hash_crack.py b/tests/test_hash_crack.py index 4e9e067ff..3d61d00d1 100644 --- a/tests/test_hash_crack.py +++ b/tests/test_hash_crack.py @@ -77,7 +77,18 @@ class _CrackBase(unittest.TestCase): conf.hashDB = None kb.wordlists = [self.wordlist] + # cracking prints "[INFO] cracked password ..." via dataToStdout(forceOutput=True), which + # bypasses both the logger and kb.wizardMode suppression; redirect stdout so the unittest + # report stays clean (these tests assert on return values/kb, never on console output). + self._saved_stdout = sys.stdout + sys.stdout = open(os.devnull, "w") + def tearDown(self): + if getattr(self, "_saved_stdout", None) is not None: + try: + sys.stdout.close() + finally: + sys.stdout = self._saved_stdout conf.disableMulti = self._saved["disableMulti"] conf.hashDB = self._saved["hashDB"] conf.hashFile = self._saved["hashFile"] diff --git a/tests/test_xpath.py b/tests/test_xpath.py index 61e8587e9..2c3dcfac1 100644 --- a/tests/test_xpath.py +++ b/tests/test_xpath.py @@ -435,6 +435,8 @@ class TestRealXPathSyntax(unittest.TestCase): payload = xpath._makePayload(original, boundary, "true()") try: count = self._count(template, payload) + except unittest.SkipTest: + raise # lxml unavailable -> skip cleanly; SkipTest is an Exception, so the broad except below would otherwise mask it into a failure except Exception as e: self.fail("Boundary '%s' in '%s' with orig='%s' invalid: %s\n payload: %s" % (bk, tkey, original, e, payload)) self.assertIsInstance(count, int,