mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-06-20 14:40:36 +00:00
117 lines
4.8 KiB
Python
117 lines
4.8 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""
|
|
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
|
|
See the file 'LICENSE' for copying permission
|
|
|
|
Core utility helpers: constant-time compare, numeric checks, safe formatting,
|
|
list/value normalization, randomness generators.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import unittest
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from _testutils import bootstrap
|
|
bootstrap()
|
|
|
|
from lib.core.common import (safeCompareStrings, isDigit, isNumber, safeStringFormat,
|
|
filterNone, flattenValue, isListLike, unArrayizeValue,
|
|
arrayizeValue, randomStr, randomInt)
|
|
|
|
|
|
class TestSafeCompareStrings(unittest.TestCase):
|
|
def test_known(self):
|
|
self.assertTrue(safeCompareStrings("abc", "abc"))
|
|
self.assertFalse(safeCompareStrings("abc", "abd"))
|
|
self.assertFalse(safeCompareStrings("test", None))
|
|
self.assertTrue(safeCompareStrings(None, None))
|
|
self.assertFalse(safeCompareStrings("a", "ab")) # different length
|
|
|
|
def test_property(self):
|
|
for s in ["", "a", "secret", "p@ss w0rd", "x" * 100]:
|
|
self.assertTrue(safeCompareStrings(s, s))
|
|
self.assertFalse(safeCompareStrings(s, s + "x"))
|
|
|
|
|
|
class TestNumericChecks(unittest.TestCase):
|
|
def test_isDigit(self):
|
|
for v, exp in [("123", True), ("0", True), ("12a", False), ("", False), ("-1", False)]:
|
|
self.assertEqual(bool(isDigit(v)), exp, msg="isDigit(%r)" % v)
|
|
|
|
def test_isNumber(self):
|
|
for v, exp in [("123", True), ("1.5", True), ("1e3", True), ("abc", False), ("", False)]:
|
|
self.assertEqual(bool(isNumber(v)), exp, msg="isNumber(%r)" % v)
|
|
|
|
|
|
class TestSafeStringFormat(unittest.TestCase):
|
|
def test_basic(self):
|
|
self.assertEqual(safeStringFormat("%s-%d", ("a", 5)), "a-5")
|
|
self.assertEqual(safeStringFormat("%s/%s", ("x", "y")), "x/y")
|
|
|
|
def test_survives_percent_in_value(self):
|
|
# the WHOLE point of safeStringFormat over plain `%`: a '%' inside an argument (common in
|
|
# payloads/URL-encoded values) must not blow up or be misread as a format spec.
|
|
# Plain "x=%s" % ("100%done",) would raise on re-evaluation; safeStringFormat must not.
|
|
self.assertEqual(safeStringFormat("x=%s", ("100%done",)), "x=100%done")
|
|
|
|
|
|
class TestListValueHelpers(unittest.TestCase):
|
|
def test_filterNone(self):
|
|
self.assertEqual(filterNone([1, None, 2, 0, "", None]), [1, 2, 0])
|
|
self.assertEqual(filterNone([]), [])
|
|
self.assertEqual(filterNone([None, None]), [])
|
|
|
|
def test_flattenValue(self):
|
|
self.assertEqual(list(flattenValue([[1, 2], [3, [4]]])), [1, 2, 3, 4])
|
|
self.assertEqual(list(flattenValue([])), [])
|
|
self.assertEqual(list(flattenValue([1])), [1])
|
|
|
|
def test_isListLike(self):
|
|
from lib.core.datatype import OrderedSet
|
|
from lib.core.bigarray import BigArray
|
|
# isListLike is sqlmap-specific: it must recognize sqlmap's own list-like containers
|
|
# (OrderedSet, BigArray), not just builtin list/tuple - that's why it's not isinstance(list)
|
|
self.assertTrue(isListLike([1]))
|
|
self.assertTrue(isListLike((1,)))
|
|
self.assertTrue(isListLike(OrderedSet([1, 2])))
|
|
self.assertTrue(isListLike(BigArray([1])))
|
|
# and must reject str (the classic trap) and dict
|
|
self.assertFalse(isListLike("string"))
|
|
self.assertFalse(isListLike({"a": 1}))
|
|
|
|
def test_arrayize_roundtrip(self):
|
|
self.assertEqual(unArrayizeValue([5]), 5)
|
|
self.assertIsNone(unArrayizeValue([]))
|
|
self.assertEqual(unArrayizeValue(7), 7)
|
|
self.assertEqual(arrayizeValue(5), [5])
|
|
self.assertEqual(arrayizeValue([5]), [5])
|
|
|
|
|
|
class TestRandomGenerators(unittest.TestCase):
|
|
def test_randomStr_length_and_alphabet(self):
|
|
for n in (1, 4, 16, 50):
|
|
self.assertEqual(len(randomStr(n)), n)
|
|
for _ in range(200):
|
|
self.assertTrue(all("a" <= c <= "z" for c in randomStr(20, lowercase=True)))
|
|
alpha = list("ABC")
|
|
for _ in range(200):
|
|
self.assertTrue(all(c in alpha for c in randomStr(20, alphabet=alpha)))
|
|
|
|
def test_randomStr_is_actually_random(self):
|
|
# guard against a hardcoded/constant return: 20-char strings must (essentially) never collide
|
|
samples = set(randomStr(20) for _ in range(100))
|
|
self.assertEqual(len(samples), 100, msg="randomStr produced collisions - not random?")
|
|
|
|
def test_randomInt_digits(self):
|
|
for n in (1, 3, 6):
|
|
lo, hi = 10 ** (n - 1), 10 ** n
|
|
for _ in range(200):
|
|
v = randomInt(n)
|
|
self.assertEqual(len(str(v)), n) # exactly n digits
|
|
self.assertTrue(lo <= v < hi, msg="randomInt(%d)=%d out of [%d,%d)" % (n, v, lo, hi))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(verbosity=2)
|