-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
Expand file tree
/
Copy pathtest_convert.py
More file actions
140 lines (107 loc) · 5.92 KB
/
Copy pathtest_convert.py
File metadata and controls
140 lines (107 loc) · 5.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
See the file 'LICENSE' for copying permission
Encoding / decoding / serialization round-trips and known vectors.
Covers: hex, base64 (std + url-safe), DBMS hex decode, byte<->text conversion,
JSON (de)serialization, restricted base64-pickle.
"""
import os
import random
import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from _testutils import bootstrap
bootstrap()
from lib.core.convert import (decodeHex, encodeHex, decodeBase64, encodeBase64,
getBytes, getText, getUnicode, getOrds,
jsonize, dejsonize, serializeValue, deserializeValue)
from lib.core.common import decodeDbmsHexValue
try:
unichr = unichr
except NameError:
unichr = chr
RND = random.Random(0xC0FFEE)
def _rand_bytes(maxlen=48):
return bytes(bytearray(RND.randint(0, 255) for _ in range(RND.randint(0, maxlen))))
class TestHex(unittest.TestCase):
def test_known_vectors(self):
self.assertEqual(decodeHex("31323334", binary=True), b"1234")
self.assertEqual(getText(encodeHex(b"1234", binary=False)), "31323334")
def test_roundtrip_property(self):
for _ in range(3000):
raw = _rand_bytes()
self.assertEqual(decodeHex(encodeHex(raw, binary=False), binary=True), raw)
class TestBase64(unittest.TestCase):
def test_known_vectors(self):
self.assertEqual(decodeBase64("MTIz", binary=True), b"123")
self.assertEqual(decodeBase64("MTIzNA", binary=True), b"1234") # missing padding
self.assertEqual(decodeBase64("MTIzNA==", binary=True), b"1234")
self.assertEqual(getText(encodeBase64(b"123", binary=False)), "MTIz")
# url-safe and standard alphabets must decode equivalently
self.assertEqual(decodeBase64("A-B_CDE", binary=True), decodeBase64("A+B/CDE", binary=True))
def test_roundtrip_property(self):
for _ in range(3000):
raw = _rand_bytes()
self.assertEqual(decodeBase64(encodeBase64(raw, binary=True), binary=True), raw)
self.assertEqual(decodeBase64(encodeBase64(raw, binary=True, safe=True), binary=True), raw)
self.assertEqual(decodeBase64(encodeBase64(raw, binary=True, padding=False), binary=True), raw)
class TestDecodeDbmsHexValue(unittest.TestCase):
# authoritative vectors taken from the function's own doctests
def test_known_vectors(self):
self.assertEqual(decodeDbmsHexValue("3132332031"), u"123 1")
self.assertEqual(decodeDbmsHexValue("31003200330020003100"), u"123 1") # utf-16-le shaped
self.assertEqual(decodeDbmsHexValue("00310032003300200031"), u"123 1") # utf-16-be shaped
self.assertEqual(decodeDbmsHexValue("0x31003200330020003100"), u"123 1")
self.assertEqual(decodeDbmsHexValue("313233203"), u"123 ?") # odd length
self.assertEqual(decodeDbmsHexValue(["0x31", "0x32"]), [u"1", u"2"]) # list input
def test_ascii_roundtrip_property(self):
for _ in range(1000):
s = "".join(chr(RND.randint(0x20, 0x7e)) for _ in range(RND.randint(1, 30)))
if len(s) % 2 == 0: # avoid the deliberate odd-length '?' behavior
self.assertEqual(decodeDbmsHexValue(getText(encodeHex(getBytes(s), binary=False))), s)
class TestByteTextConversion(unittest.TestCase):
def test_ascii_roundtrip(self):
for _ in range(1000):
s = u"".join(unichr(RND.randint(0x20, 0x7e)) for _ in range(RND.randint(0, 30)))
self.assertEqual(getUnicode(getBytes(s)), s)
def test_unicode_roundtrip(self):
samples = [u"café", u"你好", u"\U0001F600", u"a’b™c"]
for s in samples:
self.assertEqual(getUnicode(getBytes(s)), s)
def test_getords(self):
self.assertEqual(getOrds(b"AB"), [65, 66])
class TestJson(unittest.TestCase):
def test_roundtrip(self):
for obj in [{"a": 1, "b": [1, 2, 3]}, [1, "x", None], {"nested": {"k": "v"}}, "str", 123]:
self.assertEqual(dejsonize(jsonize(obj)), obj)
def test_jsonize_produces_text_not_identity(self):
# anchor: jsonize must serialize to a JSON string, not pass the object through
out = jsonize({"a": 1})
self.assertIsInstance(out, str)
self.assertIn('"a"', out)
self.assertEqual(jsonize(123), "123") # int -> textual "123"
class TestSerialize(unittest.TestCase):
# Smoke coverage of the safe (JSON-based) session serializer; the exhaustive corner-case
# and security suite lives in tests/test_serialize.py.
def test_roundtrip_allowed_types(self):
for obj in [[1, 2, 3], {"a": 1}, (1, 2), "text", 42, 3.14, True, None, {"k": [1, {"n": "v"}]}]:
self.assertEqual(deserializeValue(serializeValue(obj)), obj)
def test_bytes_roundtrip(self):
for raw in [b"x", b"\x00\x01\xff", b"\xde\xad\xbe\xef"]:
self.assertEqual(deserializeValue(serializeValue(raw)), raw, msg="bytes round-trip %r" % raw)
def test_bytes_nested_in_container_roundtrip(self):
for obj in [{"a": b"bytes"}, [b"ab", "s", 1, None], ("t", b"\xde\xad")]:
self.assertEqual(deserializeValue(serializeValue(obj)), obj, msg="nested-bytes round-trip %r" % (obj,))
def test_output_is_plain_ascii_text_no_base64(self):
# the serialized form must be readable JSON text (not Base64 / binary) so it lands verbatim in
# the TEXT session column with zero wrapping overhead
out = serializeValue({"k": [1, (2, 3)]})
self.assertIsInstance(out, str)
self.assertTrue(out.startswith("{") and out.endswith("}"), out)
def test_deserialize_accepts_bytes(self):
# BigArray hands the serialized data back as bytes (off a compressed disk chunk)
self.assertEqual(deserializeValue(getBytes(serializeValue([1, (2, 3)]))), [1, (2, 3)])
if __name__ == "__main__":
unittest.main(verbosity=2)