├── .coveragerc
├── .gitignore
├── .gitmodules
├── .travis.yml
├── Dockerfile
├── README.md
├── bkpctf
├── bkpctf_crc_mod.py
├── bkpctf_crc_mod_run.py
├── bkpctf_crc_orig.py
├── cipher.py
├── cipher_mod.py
├── encrypted.txt
├── notes
├── test.py
├── test2.py
├── test_7.py
├── test_7_run.py
├── test_augassign_list.py
├── test_list_index.py
├── tmp.py
├── writeup_notes
└── z3_test.py
├── chals
├── docs
├── Makefile
├── about.rst
├── api
│ ├── Project.rst
│ ├── index.rst
│ ├── modules.old
│ ├── pyObjectManager.rst
│ ├── pyPath.rst
│ ├── pyPathGroup.rst
│ ├── pyState.rst
│ └── pyState
│ │ └── pyState.functions.rst
├── conf.py
├── examples.rst
├── hooking.rst
├── index.rst
├── installation.rst
├── make.bat
├── quickstart.rst
├── requirements
├── what_is_implemented.rst
└── z3-4.6.0-x64-ubuntu-16.04
│ ├── LICENSE.txt
│ ├── bin
│ ├── Microsoft.Z3.dll
│ ├── Microsoft.Z3.xml
│ ├── com.microsoft.z3.jar
│ ├── libz3.a
│ ├── libz3.so
│ ├── libz3java.so
│ ├── python
│ │ ├── example.py
│ │ └── z3
│ │ │ ├── __init__.py
│ │ │ ├── z3.py
│ │ │ ├── z3consts.py
│ │ │ ├── z3core.py
│ │ │ ├── z3num.py
│ │ │ ├── z3poly.py
│ │ │ ├── z3printer.py
│ │ │ ├── z3rcf.py
│ │ │ ├── z3types.py
│ │ │ └── z3util.py
│ └── z3
│ └── include
│ ├── z3++.h
│ ├── z3.h
│ ├── z3_algebraic.h
│ ├── z3_api.h
│ ├── z3_ast_containers.h
│ ├── z3_fixedpoint.h
│ ├── z3_fpa.h
│ ├── z3_interp.h
│ ├── z3_macros.h
│ ├── z3_optimization.h
│ ├── z3_polynomial.h
│ ├── z3_rcf.h
│ ├── z3_spacer.h
│ └── z3_v1.h
├── fix_git.sh
├── pySym
├── Colorer.py
├── Config.py
├── Factory.py
├── Project.py
├── __init__.py
├── ast_parse.py
├── pyObjectManager
│ ├── BitVec.py
│ ├── Char.py
│ ├── Ctx.py
│ ├── Int.py
│ ├── List.py
│ ├── Real.py
│ ├── String.py
│ ├── __init__.py
│ └── decorators.py
├── pyPath.py
├── pyPathGroup.py
└── pyState
│ ├── Assert.py
│ ├── Assign.py
│ ├── AugAssign.py
│ ├── BinOp.py
│ ├── BoolOp.py
│ ├── Break.py
│ ├── Call.py
│ ├── Compare.py
│ ├── Expr.py
│ ├── For.py
│ ├── FunctionDef.py
│ ├── GeneratorExp.py
│ ├── If.py
│ ├── ListComp.py
│ ├── Pass.py
│ ├── Return.py
│ ├── Subscript.py
│ ├── UnaryOp.py
│ ├── While.py
│ ├── __init__.py
│ ├── functions
│ ├── List
│ │ ├── __init__.py
│ │ ├── append.py
│ │ ├── clear.py
│ │ └── insert.py
│ ├── String
│ │ ├── index.py
│ │ ├── join.py
│ │ ├── rstrip.py
│ │ └── zfill.py
│ ├── __init__.py
│ ├── abs.py
│ ├── bin.py
│ ├── chr.py
│ ├── hex.py
│ ├── int.py
│ ├── len.py
│ ├── ord.py
│ ├── print.py
│ ├── pyState
│ │ ├── BVS.py
│ │ ├── BVV.py
│ │ ├── Int.py
│ │ ├── Real.py
│ │ └── String.py
│ ├── random
│ │ └── randint.py
│ ├── range.py
│ ├── str.py
│ └── zip.py
│ └── z3Helpers.py
├── run_tests.sh
├── setup.cfg
├── setup.py
├── setup_detectOS.sh
└── tests
├── __init__.py
├── functions
├── List
│ └── test_function_List_insert.py
└── random
│ └── test_randint.py
├── longer_tests
└── test_one.py
├── scripts
├── assert_script_1.py
├── basic_function.py
└── ord_symbolic_chr.py
├── test_function_List.py
├── test_function_List_clear.py
├── test_function_String_index.py
├── test_function_String_join.py
├── test_function_String_rstrip.py
├── test_function_String_zfill.py
├── test_function_abs.py
├── test_function_bin.py
├── test_function_chr.py
├── test_function_hex.py
├── test_function_int.py
├── test_function_len.py
├── test_function_ord.py
├── test_function_pyState_BVS.py
├── test_function_pyState_BVV.py
├── test_function_pyState_Real.py
├── test_function_pyState_String.py
├── test_function_range.py
├── test_function_str.py
├── test_function_zip.py
├── test_path.py
├── test_project.py
├── test_pyObjectManager.py
├── test_pyObjectManager_BitVec.py
├── test_pyObjectManager_Char.py
├── test_pyObjectManager_Int.py
├── test_pyObjectManager_List.py
├── test_pyObjectManager_Real.py
├── test_pyObjectManager_String.py
├── test_pyPathGroup.py
├── test_pyState_Assert.py
├── test_pyState_AugAssign.py
├── test_pyState_BinOp.py
├── test_pyState_Break.py
├── test_pyState_Call.py
├── test_pyState_Compare.py
├── test_pyState_For.py
├── test_pyState_FuncionDef.py
├── test_pyState_GeneratorExp.py
├── test_pyState_If.py
├── test_pyState_ListComp.py
├── test_pyState_Pass.py
├── test_pyState_Subscript.py
├── test_pyState_UnaryOp.py
├── test_pyState_While.py
└── test_state.py
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | omit = pySym/Colorer.py
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .cache/
2 | .coverage
3 | *.swp
4 | htmlcov
5 | *.pyc
6 | test
7 | docs/_build
8 | *.egg-info/
9 | .eggs/
10 | .coverage.pysym*
11 | .pytest_cache
12 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "lib/z3"]
2 | path = lib/z3
3 | url = https://github.com/Z3Prover/z3.git
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | sudo: required
3 | services:
4 | - docker
5 | python:
6 | - 3.6
7 | before_install:
8 | - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
9 | - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
10 | - sudo apt-get update
11 | - sudo apt-get -y install docker-ce
12 | install:
13 | - docker build -t bannsec/pysym .
14 | script:
15 | - docker run -it --rm -e COVERALLS_REPO_TOKEN=$COVERALLS_REPO_TOKEN -e TRAVIS_BRANCH=$TRAVIS_BRANCH bannsec/pysym bash -c '. ~/.virtualenvs/pySym/bin/activate && cd /home/pySym/pySym/ && pytest && if [ ! -z "$COVERALLS_REPO_TOKEN" ]; then coveralls; fi'
16 | env:
17 | global:
18 | secure: GkgOfJq14ozjJ0dUtOAduBTyIBIGgI17EGSeJ6ypxYVZhEk5O10lJoY/cPHltJ11RcTAcGZmUYkAgGa+GgmY1csotqBpNOfuojYOCZst27v20khjPxkbRSwpokwoyi4jhv/HtlOVTUW808uZpa+vLs0B8w+atRO87wt7UucB98W1jqiveRrzJaiQsqCvImuZp93d1gocE7/TPLAC5KObNcmkdkFsVhZZGijWO66OvRcXUaiL7oDqY6KhxVP4lk73q4LRnok7/XBmIVhRrHhPzxigxGf+KB9nFv5iV76xRJ4gDlvPrPk5y7mkPnuUKp4FsoLWJHF/PtXOpwkqpAUVBWl3swDiIfMOMalqbHTyOW+hWlN7h8Bz9CCBXxZlDjT8O4NJKoldsVNb93vhkjWPBtR31GPnZ5uIS0MHVz/V/bp+gZghpFXOPkOF6xnL6pmuv0fY5MkNPtyTLy41hiJQlLmsNomzRMfnkGqNDlkefStr32f9ttxx9AOjk0arMX7ryAdZgPSSony+lgjb6wXhRYyxNCZL8RdKD+y4JE/e+uyMJPnlBicwSXN6/38qRGV8rvSu0UeJ7OaIbe7Ogq0Liy5gKlUY2LRX2N8nqnCeepqjidyHqTianpPN+nJJkqIrfZKtbC/IpaOontan6+403OhrkOFJN3CNenjT3IVpycY=
19 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:bionic
2 |
3 | # Root commands
4 | RUN apt-get update && apt-get install -y python3 python3-virtualenv sudo git binutils g++ gcc make libdpkg-perl python-dev libpython3.6-dev coreutils wget && \
5 | rm -rf /var/lib/apt/lists/* && \
6 | useradd -m pySym && \
7 | echo 'pySym ALL=(ALL) NOPASSWD:ALL' | sudo EDITOR='tee -a' visudo
8 |
9 | WORKDIR /home/pySym
10 |
11 | USER pySym
12 |
13 | COPY . /home/pySym/pySym/
14 |
15 | RUN mkdir /home/pySym/.virtualenvs && \
16 | sudo chown -R pySym:pySym /home/pySym/. && \
17 | python3 -m virtualenv --python=$(which python3) ~/.virtualenvs/pySym && \
18 | echo ". ~/.virtualenvs/pySym/bin/activate" >> ~/.bashrc && \
19 | . ~/.virtualenvs/pySym/bin/activate && cd pySym && PYSYM_NO_Z3=True pip install -e .[dev] && \
20 | cd lib/z3 && python scripts/mk_make.py --python && \
21 | cd build && make -j$(nproc) && make install
22 |
23 | CMD ["/bin/bash","-i"]
24 |
--------------------------------------------------------------------------------
/bkpctf/bkpctf_crc_mod.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | def to_bits(length, N):
3 | #return [int(i) for i in bin(N)[2:].zfill(length)]
4 | out = []
5 | for i in range(length):
6 | out.insert(0, pyState.BVV((N >> i) & 1,1))
7 | return out
8 |
9 | def from_bits(N):
10 | return int("".join(str(i) for i in N), 2)
11 |
12 | CRC_POLY = to_bits(65, (2**64) + 0xeff67c77d13835f7)
13 | CONST = to_bits(64, 0xabaddeadbeef1dea)
14 |
15 | pass
16 |
17 | def crc(mesg):
18 | mesg += CONST
19 | shift = 151 # 0
20 | while shift < len(mesg) - 64:
21 | #pass
22 | if mesg[shift]:
23 | for i in range(65):
24 | mesg[shift + i] ^= CRC_POLY[i]
25 | shift += 1
26 | return mesg[-64:]
27 |
28 | """
29 | from copy import copy
30 | import z3
31 | import pySym
32 |
33 | proj = pySym.Project("./bkpctf_crc_mod.py")
34 |
35 |
36 | shift = int(state.getVar('shift'))
37 | CRC_POLY = state.getVar('CRC_POLY', ctx=0)
38 | Then = []
39 | Else = []
40 | If = copy(mesg[shift]).getZ3Object() != 0
41 |
42 | for i in range(65):
43 | old_c = copy(mesg[shift+i])
44 | new_c = mesg[shift+i]
45 | new_c.increment()
46 | Then.append(new_c.getZ3Object() == old_c.getZ3Object() ^ CRC_POLY[i].getZ3Object())
47 | Else.append(new_c.getZ3Object() == old_c.getZ3Object())
48 |
49 | state.addConstraint(z3.If(If, z3.And(Then), z3.And(Else)))
50 | """
51 |
52 | INNER = to_bits(8, 0x36) * 8
53 | OUTER = to_bits(8, 0x5c) * 8
54 |
55 | """
56 | def xor(x, y):
57 | return [g ^ h for (g, h) in zip(x, y)]
58 | """
59 |
60 | def xor(x, y):
61 | l = []
62 | for i in range(len(x)):
63 | l.append(x[i] ^ y[i])
64 | pass
65 | return l
66 |
67 | """
68 | def hmac(h, key, mesg):
69 | return h(xor(key, OUTER) + h(xor(key, INNER) + mesg))
70 | """
71 |
72 | def hmac(key, mesg):
73 | return crc(xor(key, OUTER) + crc(xor(key, INNER) + mesg))
74 |
75 | PLAIN_1 = "zupe zecret"
76 | PLAIN_2 = "BKPCTF"
77 |
78 | def str_to_bits(s):
79 | return [b for i in s for b in to_bits(8, ord(i))]
80 |
81 | def bits_to_hex(b):
82 | return hex(from_bits(b)).rstrip("L")
83 | #
84 | # Create key
85 | #
86 |
87 | KEY = []
88 | for i in range(64):
89 | KEY.append(pyState.BVS(1))
90 |
91 | #p1 = hmac(crc, KEY, str_to_bits(PLAIN_1))
92 | p1 = hmac(KEY, str_to_bits(PLAIN_1))
93 |
94 | # to_bits(64, 0xa57d43a032feb286) == [1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0]
95 |
96 | """
97 | if __name__ == "__main__":
98 | with open("key.txt") as f:
99 | KEY = to_bits(64, int(f.read().strip("\n"), 16))
100 | print PLAIN_1, "=>", bits_to_hex(hmac(crc, KEY, str_to_bits(PLAIN_1))) # Should equal 0xa57d43a032feb286
101 | print "BKPCTF{" + bits_to_hex(hmac(crc, KEY, str_to_bits(PLAIN_2))) + "}"
102 | """
103 |
--------------------------------------------------------------------------------
/bkpctf/bkpctf_crc_mod_run.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from copy import copy
3 | import z3
4 | import pySym
5 | import IPython
6 |
7 | proj = pySym.Project("./bkpctf_crc_mod.py")
8 |
9 | def hook_crc(state):
10 | shift = int(state.getVar('shift'))
11 | mesg = state.getVar('mesg')
12 | CRC_POLY = state.getVar('CRC_POLY', ctx=0)
13 | Then = []
14 | Else = []
15 | If = copy(mesg[shift]).getZ3Object() != 0
16 |
17 | print("Hit hook. Shift == " + str(shift))
18 | print("Len msg == " + str(len(mesg)))
19 |
20 | for i in range(65):
21 | old_c = copy(mesg[shift+i])
22 | new_c = mesg[shift+i]
23 | new_c.increment()
24 | Then.append(new_c.getZ3Object() == old_c.getZ3Object() ^ CRC_POLY[i].getZ3Object())
25 | Else.append(new_c.getZ3Object() == old_c.getZ3Object())
26 |
27 | state.addConstraint(z3.If(If, z3.And(Then), z3.And(Else)))
28 | mesg = state.getVar('mesg')[-64:]
29 | #print([c.state for c in mesg])
30 | #print(state)
31 |
32 | def hook_interactive(state):
33 | IPython.embed()
34 |
35 | proj.hook(21, hook_crc)
36 | #proj.hook(64, hook_interactive)
37 | pg = proj.factory.path_group(ignore_groups='deadended')
38 |
39 | pg.explore()
40 |
--------------------------------------------------------------------------------
/bkpctf/bkpctf_crc_orig.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | def to_bits(length, N):
3 | return [int(i) for i in bin(N)[2:].zfill(length)]
4 |
5 | def from_bits(N):
6 | return int("".join(str(i) for i in N), 2)
7 |
8 | CRC_POLY = to_bits(65, (2**64) + 0xeff67c77d13835f7)
9 | CONST = to_bits(64, 0xabaddeadbeef1dea)
10 |
11 | def crc(mesg):
12 | print(len(mesg))
13 | mesg += CONST
14 | shift = 0
15 | while shift < len(mesg) - 64:
16 | if mesg[shift]:
17 | for i in range(65):
18 | mesg[shift + i] ^= CRC_POLY[i]
19 | shift += 1
20 | return mesg[-64:]
21 |
22 | INNER = to_bits(8, 0x36) * 8
23 | OUTER = to_bits(8, 0x5c) * 8
24 |
25 | def xor(x, y):
26 | return [g ^ h for (g, h) in zip(x, y)]
27 |
28 | def hmac(h, key, mesg):
29 | return h(xor(key, OUTER) + h(xor(key, INNER) + mesg))
30 |
31 | PLAIN_1 = "zupe zecret"
32 | PLAIN_2 = "BKPCTF"
33 |
34 | def str_to_bits(s):
35 | return [b for i in s for b in to_bits(8, ord(i))]
36 |
37 | def bits_to_hex(b):
38 | return hex(from_bits(b)).rstrip("L")
39 |
40 | if __name__ == "__main__":
41 | with open("key.txt") as f:
42 | KEY = to_bits(64, int(f.read().strip("\n"), 16))
43 | print PLAIN_1, "=>", bits_to_hex(hmac(crc, KEY, str_to_bits(PLAIN_1)))
44 | print "BKPCTF{" + bits_to_hex(hmac(crc, KEY, str_to_bits(PLAIN_2))) + "}"
45 |
--------------------------------------------------------------------------------
/bkpctf/cipher.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python2
2 |
3 | import sys
4 | import random
5 |
6 | key = sys.argv[1]
7 | flag = '**CENSORED**'
8 |
9 | assert len(key) == 13
10 | assert max([ord(char) for char in key]) < 128
11 | assert max([ord(char) for char in flag]) < 128
12 |
13 | message = flag + "|" + key
14 |
15 | encrypted = chr(random.randint(0, 128))
16 |
17 | for i in range(0, len(message)):
18 | encrypted += chr((ord(message[i]) + ord(key[i % len(key)]) + ord(encrypted[i])) % 128)
19 |
20 | print(encrypted.encode('hex'))
21 |
--------------------------------------------------------------------------------
/bkpctf/cipher_mod.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python2
2 |
3 | key = pyState.String(13)
4 | flag = pyState.String(21) # Calculated length
5 |
6 | assert len(key) == 13
7 |
8 | #assert max([ord(char) for char in key]) < 128
9 |
10 | for char in key:
11 | assert ord(char) < 128
12 |
13 | #assert max([ord(char) for char in flag]) < 128
14 | for char in flag:
15 | assert ord(char) < 128
16 |
17 | message = flag + "|" + key
18 |
19 | encrypted = chr(random.randint(0, 128))
20 |
21 | for i in range(0, len(message)):
22 | encrypted += chr((ord(message[i]) + ord(key[i % len(key)]) + ord(encrypted[i])) % 128)
23 |
24 | #print(encrypted.encode('hex'))
25 |
--------------------------------------------------------------------------------
/bkpctf/encrypted.txt:
--------------------------------------------------------------------------------
1 | 7c153a474b6a2d3f7d3f7328703e6c2d243a083e2e773c45547748667c1511333f4f745e
2 |
--------------------------------------------------------------------------------
/bkpctf/test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | def to_bits(length, N):
3 | #return [int(i) for i in bin(N)[2:].zfill(length)]
4 | out = []
5 | for i in range(length):
6 | out.insert(0, pyState.BVV((N >> i) & 1,1))
7 | return out
8 |
9 | def from_bits(N):
10 | return int("".join(str(i) for i in N), 2)
11 |
12 | CRC_POLY = to_bits(65, (2**64) + 0xeff67c77d13835f7)
13 | CONST = to_bits(64, 0xabaddeadbeef1dea)
14 |
15 | def crc(mesg):
16 | mesg += CONST
17 | shift = 0
18 | while shift < len(mesg) - 64:
19 | if mesg[shift]:
20 | for i in range(65):
21 | mesg[shift + i] ^= CRC_POLY[i]
22 | shift += 1
23 | return mesg[-64:]
24 |
25 | INNER = to_bits(8, 0x36) * 8
26 | OUTER = to_bits(8, 0x5c) * 8
27 |
28 | """
29 | def xor(x, y):
30 | return [g ^ h for (g, h) in zip(x, y)]
31 | """
32 |
33 | def xor(x, y):
34 | l = []
35 | for i in range(len(x)):
36 | l.append(x[i] ^ y[i])
37 | return l
38 |
39 | """
40 | def hmac(h, key, mesg):
41 | return h(xor(key, OUTER) + h(xor(key, INNER) + mesg))
42 | """
43 |
44 | def hmac(key, mesg):
45 | return crc(xor(key, OUTER) + crc(xor(key, INNER) + mesg))
46 |
47 | PLAIN_1 = "zupe zecret"
48 | PLAIN_2 = "BKPCTF"
49 |
50 | def str_to_bits(s):
51 | return [b for i in s for b in to_bits(8, ord(i))]
52 |
53 | def bits_to_hex(b):
54 | return hex(from_bits(b)).rstrip("L")
55 | #
56 | # Create key
57 | #
58 |
59 | KEY = []
60 | for i in range(64):
61 | KEY.append(pyState.BVS(1))
62 |
63 | #plain = str_to_bits(PLAIN_1)
64 | p1 = hmac(KEY, str_to_bits(PLAIN_1))
65 |
66 | # to_bits(64, 0xa57d43a032feb286) == [1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0]
67 |
68 | """
69 | if __name__ == "__main__":
70 | with open("key.txt") as f:
71 | KEY = to_bits(64, int(f.read().strip("\n"), 16))
72 | print PLAIN_1, "=>", bits_to_hex(hmac(crc, KEY, str_to_bits(PLAIN_1))) # Should equal 0xa57d43a032feb286
73 | print "BKPCTF{" + bits_to_hex(hmac(crc, KEY, str_to_bits(PLAIN_2))) + "}"
74 | """
75 |
--------------------------------------------------------------------------------
/bkpctf/test2.py:
--------------------------------------------------------------------------------
1 | x = 0
2 | y = 0
3 |
4 | y += 12
5 |
6 | if y > 0:
7 | x = 1
8 | else:
9 | x = 0
10 |
11 |
--------------------------------------------------------------------------------
/bkpctf/test_7.py:
--------------------------------------------------------------------------------
1 |
2 | x = 1
3 | #s = pyState.String(2)
4 | #x = "_"
5 | #x += "testt".rstrip(s)
6 |
--------------------------------------------------------------------------------
/bkpctf/test_7_run.py:
--------------------------------------------------------------------------------
1 | import pySym
2 |
3 | proj = pySym.Project("./test_7.py")
4 | pg = proj.factory.path_group()
5 | pg.explore()
6 |
--------------------------------------------------------------------------------
/bkpctf/test_augassign_list.py:
--------------------------------------------------------------------------------
1 |
2 | l1 = [1,2,3]
3 | l1 *= 3
4 |
--------------------------------------------------------------------------------
/bkpctf/test_list_index.py:
--------------------------------------------------------------------------------
1 |
2 | l = [1,2,3,4]
3 | x = l[-2:]
4 | y = l[-3:-1]
5 |
--------------------------------------------------------------------------------
/bkpctf/tmp.py:
--------------------------------------------------------------------------------
1 | def egcd(a, b):
2 | if a == 0:
3 | return (b, 0, 1)
4 | else:
5 | g, y, x = egcd(b % a, a)
6 | return (g, x - (b // a) * y, y)
7 |
8 | def modinv(a, m):
9 | g, x, y = egcd(a, m)
10 | if g != 1:
11 | raise Exception('modular inverse does not exist')
12 | else:
13 | return x % m
14 |
--------------------------------------------------------------------------------
/bkpctf/z3_test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import pySym
4 |
5 | proj = pySym.Project("./cipher_mod.py",debug=True)
6 | pg = proj.factory.path_group()
7 | pg.explore()
8 |
9 | print("When z3 doesn't freeze, i should make it here in about 30 seconds. Otherwise, it will take infinite amount of time.")
10 |
--------------------------------------------------------------------------------
/chals:
--------------------------------------------------------------------------------
1 | Challenges that should be doable to attempt to get pySym to work with
2 | -----------------------------------
3 |
4 | Boston Key Party 2016 -- HMAC CRC
5 | https://github.com/ctfs/write-ups-2016/blob/master/boston-key-party-2016/crypto/hamc_crc-5/0c7433675c3c555afb77271d6a549bf5d941d2ab
6 |
7 | SECCON Quals 2017 -- Crypto Vigenere
8 | https://github.com/p4-team/ctf/tree/master/2017-12-09-seccon-quals/crypto_vigenere
9 |
--------------------------------------------------------------------------------
/docs/about.rst:
--------------------------------------------------------------------------------
1 | ========================
2 | About pySym
3 | ========================
4 |
5 | Introduction to ``pySym``
6 | ==========================
7 |
8 | ``pySym`` is a python application that utilizes the Microsoft Z3 Theorem
9 | Prover to solve it's constraints. The goal for this application is to
10 | faithfully execute *basic* python scripts and provide a means to analyze them
11 | symbolically. Note that this application will not allow you to test your python
12 | apps for python interpreter version dependent bugs. It will attempt to follow
13 | what Python *should* be doing and thus would be more appropriate for the
14 | following two cases:
15 |
16 | 1) Finding logic bugs in your application.
17 | 2) Discovering possibly unused code segments
18 | 3) Generating test cases
19 | 4) Rapidly prototyping concepts for symbolic analysis
20 |
21 | Python Versions
22 | ========================
23 | pySym is written in Python 3 and will parse Python 3 code. It will likely not
24 | parse Python 2 code, however small code can simple be auto-upgraded if need be
25 | by the 2to3 script.
26 |
27 | pySym Weaknesses
28 | ========================
29 | ``pySym`` is not, nor will it ever be, a complete Python Symbolic Execution
30 | Engine. Scripted languages are rapidly evolving, and Python is no exception.
31 | Rapid evolution aside, even between minor versions of Python there are many
32 | small changes that will cause unintended code paths. Likely it is not feasible
33 | for any script based Symbolic Execution of Python to be that thorough.
34 |
35 | If your goal is faithful Python symbolic exeuction to any given Python
36 | major/minor versions, I'd recommend looking at a project called `CHEF
37 | `_. This project is a novel approach whereby
38 | the authors instrument the source interpreter with the `S2E
39 | `_ framework thereby causing very thorough code path
40 | generation.
41 |
42 | pySym Strengths
43 | ========================
44 | ``pySym`` is an attempt at generalizing Python Symbolic Execution utilizing
45 | Python itself. One major downfall that approaches such as CHEF have is that it
46 | is unable to make symbolic input aside from int and string types. With
47 | ``pySym``, already it has the ability to produce fully symbolic ints, floats,
48 | lists, and strings. When more datatypes are added, they will have the ability
49 | to be fully symbolic as well. This is important when you want to stress test
50 | symbolic Dictionaries or other more complex objects.
51 |
52 | It is also easy to use. Simply run the installer, load up the script you want
53 | to execute (with or without changes), and tell ``pySym`` to explore. It's not
54 | dependent on compiling special versions of applications or using strange
55 | commands that you're not quite sure what you're doing. You can be up and
56 | running in as little as 10 minutes.
57 |
58 | As a follow-on, because everything can be symbolic and you can prototype Python
59 | code in general quickly, ``pySym`` gives you a way to explore concepts without
60 | needing to be a symbolic exeuction expert. Simply write your code as you would
61 | normally for Python, then run it through ``pySym``.
62 |
--------------------------------------------------------------------------------
/docs/api/Project.rst:
--------------------------------------------------------------------------------
1 | Project
2 | =======
3 |
4 | .. automodule:: pySym.Project
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/api/index.rst:
--------------------------------------------------------------------------------
1 | ####################################
2 | API
3 | ####################################
4 |
5 | What follows is ``pySym`` core API documentation.
6 |
7 | .. note::
8 | This documentation is a work in progress. Not everything is
9 | documented yet.
10 |
11 | .. toctree::
12 | :maxdepth: 20
13 | :glob:
14 |
15 | *
16 |
--------------------------------------------------------------------------------
/docs/api/modules.old:
--------------------------------------------------------------------------------
1 | pySym
2 | =====
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | pyObjectManager
8 | pyPath
9 | pyPathGroup
10 | pyState
11 |
--------------------------------------------------------------------------------
/docs/api/pyObjectManager.rst:
--------------------------------------------------------------------------------
1 | pyObjectManager
2 | =======================
3 |
4 | Submodules
5 | ----------
6 |
7 | pyObjectManager.BitVec module
8 | -----------------------------
9 |
10 | .. automodule:: pySym.pyObjectManager.BitVec
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | pyObjectManager.Char module
16 | ---------------------------
17 |
18 | .. automodule:: pySym.pyObjectManager.Char
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | pyObjectManager.Ctx module
24 | --------------------------
25 |
26 | .. automodule:: pySym.pyObjectManager.Ctx
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | pyObjectManager.Int module
32 | --------------------------
33 |
34 | .. automodule:: pySym.pyObjectManager.Int
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
39 | pyObjectManager.List module
40 | ---------------------------
41 |
42 | .. automodule:: pySym.pyObjectManager.List
43 | :members:
44 | :undoc-members:
45 | :show-inheritance:
46 |
47 | pyObjectManager.Real module
48 | ---------------------------
49 |
50 | .. automodule:: pySym.pyObjectManager.Real
51 | :members:
52 | :undoc-members:
53 | :show-inheritance:
54 |
55 | pyObjectManager.String module
56 | -----------------------------
57 |
58 | .. automodule:: pySym.pyObjectManager.String
59 | :members:
60 | :undoc-members:
61 | :show-inheritance:
62 |
63 |
64 | Module contents
65 | ---------------
66 |
67 | .. automodule:: pySym.pyObjectManager
68 | :members:
69 | :undoc-members:
70 | :show-inheritance:
71 |
--------------------------------------------------------------------------------
/docs/api/pyPath.rst:
--------------------------------------------------------------------------------
1 | pyPath
2 | =============
3 |
4 | .. automodule:: pySym.pyPath
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/api/pyPathGroup.rst:
--------------------------------------------------------------------------------
1 | pyPathGroup
2 | ==================
3 |
4 | .. automodule:: pySym.pyPathGroup
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/api/pyState.rst:
--------------------------------------------------------------------------------
1 | pyState
2 | ===============
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :glob:
9 |
10 | pyState/pyState.functions
11 |
12 | pyState.Assign
13 | ---------------------
14 |
15 | .. automodule:: pySym.pyState.Assign
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
20 |
21 | pyState.AugAssign
22 | ------------------------
23 |
24 | .. automodule:: pySym.pyState.AugAssign
25 | :members:
26 | :undoc-members:
27 | :show-inheritance:
28 |
29 | pyState.BinOp
30 | --------------------
31 |
32 | .. automodule:: pySym.pyState.BinOp
33 | :members:
34 | :undoc-members:
35 | :show-inheritance:
36 |
37 | pyState.BoolOp
38 | ---------------------
39 |
40 | .. automodule:: pySym.pyState.BoolOp
41 | :members:
42 | :undoc-members:
43 | :show-inheritance:
44 |
45 | pyState.Break
46 | --------------------
47 |
48 | .. automodule:: pySym.pyState.Break
49 | :members:
50 | :undoc-members:
51 | :show-inheritance:
52 |
53 | pyState.Call
54 | -------------------
55 |
56 | .. automodule:: pySym.pyState.Call
57 | :members:
58 | :undoc-members:
59 | :show-inheritance:
60 |
61 | pyState.Compare
62 | ----------------------
63 |
64 | .. automodule:: pySym.pyState.Compare
65 | :members:
66 | :undoc-members:
67 | :show-inheritance:
68 |
69 | pyState.Expr
70 | -------------------
71 |
72 | .. automodule:: pySym.pyState.Expr
73 | :members:
74 | :undoc-members:
75 | :show-inheritance:
76 |
77 | pyState.For
78 | ------------------
79 |
80 | .. automodule:: pySym.pyState.For
81 | :members:
82 | :undoc-members:
83 | :show-inheritance:
84 |
85 | pyState.FunctionDef
86 | --------------------------
87 |
88 | .. automodule:: pySym.pyState.FunctionDef
89 | :members:
90 | :undoc-members:
91 | :show-inheritance:
92 |
93 | pyState.GeneratorExp
94 | ---------------------------
95 |
96 | .. automodule:: pySym.pyState.GeneratorExp
97 | :members:
98 | :undoc-members:
99 | :show-inheritance:
100 |
101 | pyState.If
102 | -----------------
103 |
104 | .. automodule:: pySym.pyState.If
105 | :members:
106 | :undoc-members:
107 | :show-inheritance:
108 |
109 | pyState.ListComp
110 | -----------------------
111 |
112 | .. automodule:: pySym.pyState.ListComp
113 | :members:
114 | :undoc-members:
115 | :show-inheritance:
116 |
117 | pyState.Pass
118 | -------------------
119 |
120 | .. automodule:: pySym.pyState.Pass
121 | :members:
122 | :undoc-members:
123 | :show-inheritance:
124 |
125 | pyState.Return
126 | ---------------------
127 |
128 | .. automodule:: pySym.pyState.Return
129 | :members:
130 | :undoc-members:
131 | :show-inheritance:
132 |
133 | pyState.Subscript
134 | ------------------------
135 |
136 | .. automodule:: pySym.pyState.Subscript
137 | :members:
138 | :undoc-members:
139 | :show-inheritance:
140 |
141 | pyState.UnaryOp
142 | ----------------------
143 |
144 | .. automodule:: pySym.pyState.UnaryOp
145 | :members:
146 | :undoc-members:
147 | :show-inheritance:
148 |
149 | pyState.While
150 | --------------------
151 |
152 | .. automodule:: pySym.pyState.While
153 | :members:
154 | :undoc-members:
155 | :show-inheritance:
156 |
157 | pyState.z3Helpers
158 | ------------------------
159 |
160 | .. automodule:: pySym.pyState.z3Helpers
161 | :members:
162 | :undoc-members:
163 | :show-inheritance:
164 |
165 |
166 | Module contents
167 | ---------------
168 |
169 | .. automodule:: pySym.pyState
170 | :members:
171 | :undoc-members:
172 | :show-inheritance:
173 |
--------------------------------------------------------------------------------
/docs/api/pyState/pyState.functions.rst:
--------------------------------------------------------------------------------
1 | pyState.functions package
2 | =========================
3 |
4 | Submodules
5 | ----------
6 |
7 | pyState.functions.abs module
8 | ----------------------------
9 |
10 | .. automodule:: pySym.pyState.functions.abs
11 | :members:
12 | :undoc-members:
13 | :show-inheritance:
14 |
15 | pyState.functions.bin module
16 | ----------------------------
17 |
18 | .. automodule:: pySym.pyState.functions.bin
19 | :members:
20 | :undoc-members:
21 | :show-inheritance:
22 |
23 | pyState.functions.hex module
24 | ----------------------------
25 |
26 | .. automodule:: pySym.pyState.functions.hex
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | pyState.functions.int module
32 | ----------------------------
33 |
34 | .. automodule:: pySym.pyState.functions.int
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
39 | pyState.functions.len module
40 | ----------------------------
41 |
42 | .. automodule:: pySym.pyState.functions.len
43 | :members:
44 | :undoc-members:
45 | :show-inheritance:
46 |
47 | pyState.functions.ord module
48 | ----------------------------
49 |
50 | .. automodule:: pySym.pyState.functions.ord
51 | :members:
52 | :undoc-members:
53 | :show-inheritance:
54 |
55 | pyState.functions.print module
56 | ------------------------------
57 |
58 | .. automodule:: pySym.pyState.functions.print
59 | :members:
60 | :undoc-members:
61 | :show-inheritance:
62 |
63 | pyState.functions.range module
64 | ------------------------------
65 |
66 | .. automodule:: pySym.pyState.functions.range
67 | :members:
68 | :undoc-members:
69 | :show-inheritance:
70 |
71 | pyState.functions.str module
72 | ----------------------------
73 |
74 | .. automodule:: pySym.pyState.functions.str
75 | :members:
76 | :undoc-members:
77 | :show-inheritance:
78 |
79 | pyState.functions.zip module
80 | ----------------------------
81 |
82 | .. automodule:: pySym.pyState.functions.zip
83 | :members:
84 | :undoc-members:
85 | :show-inheritance:
86 |
87 |
88 | Module contents
89 | ---------------
90 |
91 | .. automodule:: pySym.pyState.functions
92 | :members:
93 | :undoc-members:
94 | :show-inheritance:
95 |
--------------------------------------------------------------------------------
/docs/examples.rst:
--------------------------------------------------------------------------------
1 | ========================
2 | Examples
3 | ========================
4 |
5 | Tokyo Westerns CTF 2017: My Simple Cipher
6 | =========================================
7 | External Writeup: `BannSecurity.com `_
8 |
9 | Prime Finder
10 | ========================
11 |
12 | Let's recreate a simple problem of finding all the primes under 50. Stealing
13 | and modifying some code from the internet, we can use the following python code
14 | to do just that.
15 |
16 | .. code-block:: python
17 |
18 | # Enable logging if you want. It's faster without.
19 | #import logging
20 | #logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
21 | from pySym.pyPath import Path
22 | from pySym import ast_parse
23 | from pySym import Colorer
24 | from pySym.pyPathGroup import PathGroup
25 |
26 | source = """
27 | def isprime(n):
28 |
29 | # 0 and 1 are not primes
30 | if n < 2:
31 | return 0
32 |
33 | # 2 is the only even prime number
34 | if n == 2:
35 | return 1
36 |
37 | # all other even numbers are not primes
38 | if n % 2 == 0:
39 | return 0
40 |
41 | # range starts with 3 and only needs to go up
42 | # the square root of n for all odd numbers
43 | for x in range(3, int(n**0.5) + 1, 2):
44 | if n % x == 0:
45 | return 0
46 |
47 | return 1
48 |
49 | x = [x for x in range(50) if isprime(x) == 1]
50 | """
51 |
52 | b = ast_parse.parse(source).body
53 | p = Path(b,source=source)
54 | pg = PathGroup(p,discardFailures=True)
55 |
56 | The first two lines are just to add more logging. If you're not interested in
57 | watching scrolling text, just leave those two out. Aside from that, the rest is
58 | self explanatory. As of writing, I have not implemented Bools yet, so this is
59 | why I'm returning integer 1 or 0. The end effect is the same, however.
60 |
61 | As written, this code will symbolically execute without special changes. To do
62 | so, just execute:
63 |
64 | .. code-block:: python
65 |
66 | pg.explore()
67 |
68 | This will cause `pySym` to start exploring this state and finding valid paths.
69 | Since we're only dealing with concrete variables, there will be one valid path
70 | through. However, there will be many deadended paths since `pySym` will take
71 | every branch along the way.
72 |
73 | Also note, I used "discardFailures=True" in PathGroup. This is because with
74 | this option enabled, you won't be wasting memory of your computer with
75 | deadended paths. When there are many such paths, or if the paths are
76 | complicated, the total memory used by paths you're not interested in can become
77 | high. This option allows you to immediately forget those paths and thus reduce
78 | your memory profile.
79 |
80 | Once done, we can confirm that the expected results were attained:
81 |
82 | .. code-block:: python
83 |
84 | In [7]: pg
85 | Out[7]:
86 |
87 | In [8]: x = pg.completed[0].state.getVar('x')
88 |
89 | In [9]: print(x)
90 | [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
91 |
92 | The first command simply shows us that our path group has 1 completed path. As
93 | mentioned above, there would be many more deadended paths if we hadn't set
94 | discardFailures to True. The second command reaches into our only completed
95 | path (index 0) and asks the state to give us the pyObjectManager object for
96 | variable named 'x'. We can do many things with this variable at this point,
97 | however for the purposes of this example, we simply print out the variable. It
98 | will pause for a few moments as z3 solves constraints for us and `pySym` puts
99 | it into the proper representation (a list).
100 |
101 |
102 |
--------------------------------------------------------------------------------
/docs/hooking.rst:
--------------------------------------------------------------------------------
1 | ================
2 | Symbolic Hooking
3 | ================
4 |
5 | What is Hooking
6 | ===============
7 |
8 | Hooking is a means to interject your own commands into the symbolic execution
9 | of the application. For instance, a common reason to hook a function or part of
10 | a function is to provide your own symbolic summary for it. In this way, you can
11 | jump out of the symbolically executed script, back into the engine and tell
12 | `pySym` how to keep that section symbolic.
13 |
14 | One quick example is, if you consider an if statement nested inside a while
15 | loop, as follows:
16 |
17 | .. code-block:: python
18 |
19 | def my_function(my_list):
20 | output = []
21 | for element in my_list:
22 | if element == 0:
23 | output.append("zero")
24 | else:
25 | output.append("one")
26 | return output
27 |
28 | In the above example, that ``if`` statement inside the ``for`` loop would actually
29 | cause pySym to state split for each element. Depending on the size of the input
30 | list and how symbolic the input actually is, this could cause a path explosion
31 | issue. One way around that is to hook ``my_function`` and create a summary for
32 | it.
33 |
34 | How to Hook
35 | ===========
36 | At present, hooking in `pySym` is accomplished via the `pySym.Project.hook`
37 | method.
38 |
39 | See the method documentation for more details:
40 |
41 | :meth:`pySym.Project.Project.hook`
42 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | ####################################
2 | Welcome to pySym's documentation!
3 | ####################################
4 |
5 | ``pySym`` is a Symbolic Execution Engine for Python Scripts. It is
6 | written in Python and designed for easy adoption for a subset of
7 | symbolic execution problems.
8 |
9 | ****************
10 | Getting Started
11 | ****************
12 |
13 | .. toctree::
14 | :maxdepth: 2
15 | :glob:
16 |
17 | about
18 | installation
19 | quickstart
20 | examples
21 | what_is_implemented
22 | hooking
23 | api/index
24 |
--------------------------------------------------------------------------------
/docs/quickstart.rst:
--------------------------------------------------------------------------------
1 | ========================
2 | pySym Quick-Start
3 | ========================
4 |
5 | Running Your First Program
6 | ==========================
7 |
8 | Assuming that you have already `installed `_ pySym, actiate
9 | your virtual environment and load up a source::
10 |
11 | $ workon pySym
12 | (pySym)$ ipython
13 |
14 | +++++++++++++++++
15 | Automated Loading
16 | +++++++++++++++++
17 |
18 | Assuming you have a program you want to symbolically execute called
19 | `my_test_program.py`, you can do so with the following lines:
20 |
21 | .. code-block:: python
22 |
23 | In [1]: import pySym
24 |
25 | In [2]: proj = pySym.Project("my_test_program.py")
26 |
27 | In [3]: pg = proj.factory.path_group()
28 |
29 | You can now run it by simply executing:
30 |
31 | .. code-block:: python
32 |
33 | In [4]: pg.explore()
34 |
35 | +++++++++++++++++++++
36 | Manually From Strings
37 | +++++++++++++++++++++
38 |
39 | You can also load your script directly via python string. The following example
40 | loads it from a file:
41 |
42 | .. code-block:: python
43 |
44 | In [1]: from pySym.pyPath import Path
45 |
46 | In [2]: import ast
47 |
48 | In [3]: from pySym import Colorer
49 |
50 | In [4]: from pySym.pyPathGroup import PathGroup
51 |
52 | In [5]: with open("test","r") as f:
53 | ...: b = ast.parse(source).body
54 | ...: p = Path(b,source=source)
55 | ...: pg = PathGroup(p)
56 |
57 | You can now run it by simply executing:
58 |
59 | .. code-block:: python
60 |
61 | In [6]: pg.explore()
62 |
63 | See the `examples `_ page for example programs.
64 |
--------------------------------------------------------------------------------
/docs/requirements:
--------------------------------------------------------------------------------
1 | enforce
2 | prettytable
3 |
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Z3
2 | Copyright (c) Microsoft Corporation
3 | All rights reserved.
4 | MIT License
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7 |
8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 |
10 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/Microsoft.Z3.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bannsec/pySym/497b5d84e5e360ea57ceaf26d477d3fad1d4e6c8/docs/z3-4.6.0-x64-ubuntu-16.04/bin/Microsoft.Z3.dll
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/com.microsoft.z3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bannsec/pySym/497b5d84e5e360ea57ceaf26d477d3fad1d4e6c8/docs/z3-4.6.0-x64-ubuntu-16.04/bin/com.microsoft.z3.jar
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/libz3.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bannsec/pySym/497b5d84e5e360ea57ceaf26d477d3fad1d4e6c8/docs/z3-4.6.0-x64-ubuntu-16.04/bin/libz3.a
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/libz3.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bannsec/pySym/497b5d84e5e360ea57ceaf26d477d3fad1d4e6c8/docs/z3-4.6.0-x64-ubuntu-16.04/bin/libz3.so
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/libz3java.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bannsec/pySym/497b5d84e5e360ea57ceaf26d477d3fad1d4e6c8/docs/z3-4.6.0-x64-ubuntu-16.04/bin/libz3java.so
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/python/example.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation 2015, 2016
2 |
3 | # The Z3 Python API requires libz3.dll/.so/.dylib in the
4 | # PATH/LD_LIBRARY_PATH/DYLD_LIBRARY_PATH
5 | # environment variable and the PYTHON_PATH environment variable
6 | # needs to point to the `python' directory that contains `z3/z3.py'
7 | # (which is at bin/python in our binary releases).
8 |
9 | # If you obtained example.py as part of our binary release zip files,
10 | # which you unzipped into a directory called `MYZ3', then follow these
11 | # instructions to run the example:
12 |
13 | # Running this example on Windows:
14 | # set PATH=%PATH%;MYZ3\bin
15 | # set PYTHONPATH=MYZ3\bin\python
16 | # python example.py
17 |
18 | # Running this example on Linux:
19 | # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:MYZ3/bin
20 | # export PYTHONPATH=MYZ3/bin/python
21 | # python example.py
22 |
23 | # Running this example on OSX:
24 | # export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:MYZ3/bin
25 | # export PYTHONPATH=MYZ3/bin/python
26 | # python example.py
27 |
28 |
29 | from z3 import *
30 |
31 | x = Real('x')
32 | y = Real('y')
33 | s = Solver()
34 | s.add(x + y > 5, x > 1, y > 1)
35 | print(s.check())
36 | print(s.model())
37 |
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/python/z3/__init__.py:
--------------------------------------------------------------------------------
1 | from .z3 import *
2 |
3 | from . import z3num
4 | from . import z3poly
5 | from . import z3printer
6 | from . import z3rcf
7 | from . import z3types
8 | from . import z3util
9 |
10 | # generated files
11 | from . import z3core
12 | from . import z3consts
13 |
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/python/z3/z3poly.py:
--------------------------------------------------------------------------------
1 | ############################################
2 | # Copyright (c) 2012 Microsoft Corporation
3 | #
4 | # Z3 Python interface for Z3 polynomials
5 | #
6 | # Author: Leonardo de Moura (leonardo)
7 | ############################################
8 |
9 | from .z3 import *
10 |
11 | def subresultants(p, q, x):
12 | """
13 | Return the non-constant subresultants of 'p' and 'q' with respect to the "variable" 'x'.
14 |
15 | 'p', 'q' and 'x' are Z3 expressions where 'p' and 'q' are arithmetic terms.
16 | Note that, any subterm that cannot be viewed as a polynomial is assumed to be a variable.
17 | Example: f(a) is a considered to be a variable b in the polynomial
18 |
19 | f(a)*f(a) + 2*f(a) + 1
20 |
21 | >>> x, y = Reals('x y')
22 | >>> subresultants(2*x + y, 3*x - 2*y + 2, x)
23 | [-7*y + 4]
24 | >>> r = subresultants(3*y*x**2 + y**3 + 1, 2*x**3 + y + 3, x)
25 | >>> r[0]
26 | 4*y**9 + 12*y**6 + 27*y**5 + 162*y**4 + 255*y**3 + 4
27 | >>> r[1]
28 | -6*y**4 + -6*y
29 | """
30 | return AstVector(Z3_polynomial_subresultants(p.ctx_ref(), p.as_ast(), q.as_ast(), x.as_ast()), p.ctx)
31 |
32 | if __name__ == "__main__":
33 | import doctest
34 | if doctest.testmod().failed:
35 | exit(1)
36 |
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/bin/z3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bannsec/pySym/497b5d84e5e360ea57ceaf26d477d3fad1d4e6c8/docs/z3-4.6.0-x64-ubuntu-16.04/bin/z3
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/include/z3.h:
--------------------------------------------------------------------------------
1 | /*++
2 | Copyright (c) 2007 Microsoft Corporation
3 |
4 | Module Name:
5 |
6 | z3.h
7 |
8 | Abstract:
9 |
10 | Z3 API.
11 |
12 | Author:
13 |
14 | Nikolaj Bjorner (nbjorner)
15 | Leonardo de Moura (leonardo) 2007-06-8
16 |
17 | Notes:
18 |
19 | --*/
20 |
21 | #ifndef Z3_H_
22 | #define Z3_H_
23 |
24 | #include
25 | #include "z3_macros.h"
26 | #include "z3_api.h"
27 | #include "z3_ast_containers.h"
28 | #include "z3_algebraic.h"
29 | #include "z3_polynomial.h"
30 | #include "z3_rcf.h"
31 | #include "z3_fixedpoint.h"
32 | #include "z3_optimization.h"
33 | #include "z3_interp.h"
34 | #include "z3_fpa.h"
35 | #include "z3_spacer.h"
36 | #endif
37 |
38 |
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/include/z3_macros.h:
--------------------------------------------------------------------------------
1 |
2 | /*++
3 | Copyright (c) 2015 Microsoft Corporation
4 |
5 | --*/
6 |
7 | #ifndef Z3_bool_opt
8 | #define Z3_bool_opt Z3_bool
9 | #endif
10 |
11 | #ifndef Z3_API
12 | # ifdef __GNUC__
13 | # define Z3_API __attribute__ ((visibility ("default")))
14 | # else
15 | # define Z3_API
16 | # endif
17 | #endif
18 |
19 | #ifndef DEFINE_TYPE
20 | #define DEFINE_TYPE(T) typedef struct _ ## T *T
21 | #endif
22 |
23 | #ifndef DEFINE_VOID
24 | #define DEFINE_VOID(T) typedef void* T
25 | #endif
26 |
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/include/z3_polynomial.h:
--------------------------------------------------------------------------------
1 | /*++
2 | Copyright (c) 2012 Microsoft Corporation
3 |
4 | Module Name:
5 |
6 | z3_polynomial.h
7 |
8 | Abstract:
9 |
10 | Additional APIs for polynomials.
11 |
12 | Author:
13 |
14 | Leonardo de Moura (leonardo) 2012-12-09
15 |
16 | Notes:
17 |
18 | --*/
19 |
20 | #ifndef Z3_POLYNOMIAL_H_
21 | #define Z3_POLYNOMIAL_H_
22 |
23 | #ifdef __cplusplus
24 | extern "C" {
25 | #endif // __cplusplus
26 |
27 | /** \defgroup capi C API */
28 | /*@{*/
29 |
30 |
31 | /** @name Polynomials */
32 | /*@{*/
33 |
34 | /**
35 | \brief Return the nonzero subresultants of \c p and \c q with respect to the "variable" \c x.
36 |
37 | \pre \c p, \c q and \c x are Z3 expressions where \c p and \c q are arithmetic terms.
38 | Note that, any subterm that cannot be viewed as a polynomial is assumed to be a variable.
39 | Example: f(a) is a considered to be a variable in the polynomial
40 |
41 | f(a)*f(a) + 2*f(a) + 1
42 |
43 | def_API('Z3_polynomial_subresultants', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(AST), _in(AST)))
44 | */
45 | Z3_ast_vector Z3_API Z3_polynomial_subresultants(Z3_context c, Z3_ast p, Z3_ast q, Z3_ast x);
46 |
47 |
48 | /*@}*/
49 | /*@}*/
50 |
51 | #ifdef __cplusplus
52 | }
53 | #endif // __cplusplus
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/docs/z3-4.6.0-x64-ubuntu-16.04/include/z3_v1.h:
--------------------------------------------------------------------------------
1 | /*++
2 | Copyright (c) 2011 Microsoft Corporation
3 |
4 | Module Name:
5 |
6 | z3_v1.h
7 |
8 | Abstract:
9 |
10 | Z3 1.x backwards compatibility macros.
11 | These macros are used to simulate the Z3 API using in the 1.x versions.
12 | This file should only be used by users still using the Z3 1.x API.
13 |
14 | Author:
15 |
16 | Leonardo de Moura (leonardo) 2011-09-22
17 |
18 | Notes:
19 |
20 | --*/
21 | #ifndef Z3_V1_H_
22 | #define Z3_V1_H_
23 |
24 | #include "api/z3.h"
25 |
26 | // Backwards compatibility
27 | #define Z3_type_ast Z3_sort
28 | #define Z3_const_decl_ast Z3_func_decl
29 | #define Z3_const Z3_app
30 | #define Z3_pattern_ast Z3_pattern
31 | #define Z3_UNINTERPRETED_TYPE Z3_UNINTERPRETED_SORT
32 | #define Z3_BOOL_TYPE Z3_BOOL_SORT
33 | #define Z3_INT_TYPE Z3_INT_SORT
34 | #define Z3_REAL_TYPE Z3_REAL_SORT
35 | #define Z3_BV_TYPE Z3_BV_SORT
36 | #define Z3_ARRAY_TYPE Z3_ARRAY_SORT
37 | #define Z3_TUPLE_TYPE Z3_DATATYPE_SORT
38 | #define Z3_UNKNOWN_TYPE Z3_UNKNOWN_SORT
39 | #define Z3_CONST_DECL_AST Z3_FUNC_DECL_AST
40 | #define Z3_TYPE_AST Z3_SORT_AST
41 | #define Z3_SORT_ERROR Z3_TYPE_ERROR
42 | #define Z3_mk_uninterpreted_type Z3_mk_uninterpreted_sort
43 | #define Z3_mk_bool_type Z3_mk_bool_sort
44 | #define Z3_mk_int_type Z3_mk_int_sort
45 | #define Z3_mk_real_type Z3_mk_real_sort
46 | #define Z3_mk_bv_type Z3_mk_bv_sort
47 | #define Z3_mk_array_type Z3_mk_array_sort
48 | #define Z3_mk_tuple_type Z3_mk_tuple_sort
49 | #define Z3_get_type Z3_get_sort
50 | #define Z3_get_pattern_ast Z3_get_pattern
51 | #define Z3_get_type_kind Z3_get_sort_kind
52 | #define Z3_get_type_name Z3_get_sort_name
53 | #define Z3_get_bv_type_size Z3_get_bv_sort_size
54 | #define Z3_get_array_type_domain Z3_get_array_sort_domain
55 | #define Z3_get_array_type_range Z3_get_array_sort_range
56 | #define Z3_get_tuple_type_num_fields Z3_get_tuple_sort_num_fields
57 | #define Z3_get_tuple_type_field_decl Z3_get_tuple_sort_field_decl
58 | #define Z3_get_tuple_type_mk_decl Z3_get_tuple_sort_mk_decl
59 | #define Z3_to_const_ast Z3_to_app
60 | #define Z3_get_numeral_value_string Z3_get_numeral_string
61 | #define Z3_get_const_ast_decl Z3_get_app_decl
62 | #define Z3_get_value Z3_eval_func_decl
63 |
64 | #endif
65 |
--------------------------------------------------------------------------------
/fix_git.sh:
--------------------------------------------------------------------------------
1 | # Sooo... If you want to git checkout different branches, you need to update the git repo to fetch ALL sources
2 | git config --local --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
3 |
--------------------------------------------------------------------------------
/pySym/Colorer.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # encoding: utf-8
3 | import logging
4 | # now we patch Python code to add color support to logging.StreamHandler
5 | def add_coloring_to_emit_windows(fn):
6 | # add methods we need to the class
7 | def _out_handle(self):
8 | import ctypes
9 | return ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE)
10 | out_handle = property(_out_handle)
11 |
12 | def _set_color(self, code):
13 | import ctypes
14 | # Constants from the Windows API
15 | self.STD_OUTPUT_HANDLE = -11
16 | hdl = ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE)
17 | ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, code)
18 |
19 | setattr(logging.StreamHandler, '_set_color', _set_color)
20 |
21 | def new(*args):
22 | FOREGROUND_BLUE = 0x0001 # text color contains blue.
23 | FOREGROUND_GREEN = 0x0002 # text color contains green.
24 | FOREGROUND_RED = 0x0004 # text color contains red.
25 | FOREGROUND_INTENSITY = 0x0008 # text color is intensified.
26 | FOREGROUND_WHITE = FOREGROUND_BLUE|FOREGROUND_GREEN |FOREGROUND_RED
27 | # winbase.h
28 | STD_INPUT_HANDLE = -10
29 | STD_OUTPUT_HANDLE = -11
30 | STD_ERROR_HANDLE = -12
31 |
32 | # wincon.h
33 | FOREGROUND_BLACK = 0x0000
34 | FOREGROUND_BLUE = 0x0001
35 | FOREGROUND_GREEN = 0x0002
36 | FOREGROUND_CYAN = 0x0003
37 | FOREGROUND_RED = 0x0004
38 | FOREGROUND_MAGENTA = 0x0005
39 | FOREGROUND_YELLOW = 0x0006
40 | FOREGROUND_GREY = 0x0007
41 | FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.
42 |
43 | BACKGROUND_BLACK = 0x0000
44 | BACKGROUND_BLUE = 0x0010
45 | BACKGROUND_GREEN = 0x0020
46 | BACKGROUND_CYAN = 0x0030
47 | BACKGROUND_RED = 0x0040
48 | BACKGROUND_MAGENTA = 0x0050
49 | BACKGROUND_YELLOW = 0x0060
50 | BACKGROUND_GREY = 0x0070
51 | BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
52 |
53 | levelno = args[1].levelno
54 | if(levelno>=50):
55 | color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY
56 | elif(levelno>=40):
57 | color = FOREGROUND_RED | FOREGROUND_INTENSITY
58 | elif(levelno>=30):
59 | color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY
60 | elif(levelno>=20):
61 | color = FOREGROUND_GREEN
62 | elif(levelno>=10):
63 | color = FOREGROUND_MAGENTA
64 | else:
65 | color = FOREGROUND_WHITE
66 | args[0]._set_color(color)
67 |
68 | ret = fn(*args)
69 | args[0]._set_color( FOREGROUND_WHITE )
70 | #print "after"
71 | return ret
72 | return new
73 |
74 | def add_coloring_to_emit_ansi(fn):
75 | # add methods we need to the class
76 | def new(*args):
77 | levelno = args[1].levelno
78 | if(levelno>=50):
79 | color = '\x1b[31m' # red
80 | elif(levelno>=40):
81 | color = '\x1b[31m' # red
82 | elif(levelno>=30):
83 | color = '\x1b[33m' # yellow
84 | elif(levelno>=20):
85 | color = '\x1b[32m' # green
86 | elif(levelno>=10):
87 | color = '\x1b[35m' # pink
88 | else:
89 | color = '\x1b[0m' # normal
90 | args[1].msg = color + args[1].msg + '\x1b[0m' # normal
91 | #print "after"
92 | return fn(*args)
93 | return new
94 |
95 | import platform
96 | if platform.system()=='Windows':
97 | # Windows does not support ANSI escapes and we are using API calls to set the console color
98 | logging.StreamHandler.emit = add_coloring_to_emit_windows(logging.StreamHandler.emit)
99 | else:
100 | # all non-Windows platforms are supporting ANSI escapes so we use them
101 | logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit)
102 | #log = logging.getLogger()
103 | #log.addFilter(log_filter())
104 | #//hdlr = logging.StreamHandler()
105 | #//hdlr.setFormatter(formatter())
106 |
--------------------------------------------------------------------------------
/pySym/Config.py:
--------------------------------------------------------------------------------
1 | # This file will house generic PySym config settings
2 |
3 | PYSYM_MAX_SYM_LIST_SPLIT=256
4 |
--------------------------------------------------------------------------------
/pySym/Factory.py:
--------------------------------------------------------------------------------
1 | import logging
2 | logger = logging.getLogger("Factory")
3 |
4 | import ast
5 | import enforce
6 |
7 | from .pyPath import Path
8 | from .pyPathGroup import PathGroup
9 |
10 | #@enforce.runtime_validation
11 | class Factory:
12 |
13 | __slots__ = ['__project','__weakref__']
14 |
15 | def __init__(self, project):
16 | self._project = project
17 |
18 | def path(self) -> Path:
19 | """pySym.pyPath.Path: Path object for this project."""
20 |
21 | # Read in the file
22 | with open(self._project.file_name, "r") as f:
23 | source = f.read()
24 |
25 | # Parse it
26 | body = ast.parse(source).body
27 |
28 | # Return the new path
29 | return Path(body,source=source,project=self._project)
30 |
31 | def path_group(self, *args, **kwargs) -> PathGroup:
32 | """pySym.pyPathGroup.PathGroup: Basic PathGroup object for this project."""
33 | kwargs['project'] = self._project
34 | return PathGroup(self.path(), *args, **kwargs)
35 |
36 | ##############
37 | # Properties #
38 | ##############
39 |
40 | @property
41 | def _project(self):
42 | """pySym.Project.Project: Associated Project object."""
43 | return self.__project
44 |
45 | @_project.setter
46 | def _project(self, project) -> None:
47 | if type(project) is not Project:
48 | raise Exception("Invalid type for project ({0}) should be type Project".format(type(project)))
49 |
50 | self.__project = project
51 |
52 | from .Project import Project
53 |
--------------------------------------------------------------------------------
/pySym/Project.py:
--------------------------------------------------------------------------------
1 | import logging
2 | logger = logging.getLogger("Project")
3 | from . import Colorer
4 |
5 | import enforce
6 | import os
7 | import types
8 |
9 | #@enforce.runtime_validation
10 | class Project:
11 |
12 | __slots__ = ['__file_name', '__factory', '__weakref__', '__hooks']
13 |
14 | def __init__(self, file, debug=False):
15 |
16 | if debug:
17 | logging.basicConfig(level=logging.DEBUG)
18 |
19 | self.file_name = file
20 | self.factory = Factory(self)
21 | self._hooks = {}
22 |
23 | def hook(self, address, callback):
24 | """Registers pySym to hook address and call the callback when hit.
25 |
26 | Callback function will be called with the current state as the first parameter.
27 |
28 | Args:
29 | address (int): Line number of the source code to hook this callback to.
30 | callback (types.FunctionType): Function to call when line number is hit.
31 |
32 | Example:
33 | >>> def my_callback(state):
34 | print(state)
35 | >>> project.hook(12, my_callback)
36 | """
37 | assert type(address) is int, "Unexpected address type of {}".format(type(address))
38 | assert type(callback) is types.FunctionType, "Unexpected callback type of {}".format(type(callback))
39 |
40 | # TODO: Sanity check that the number is within source range and that there's an instruction at that location
41 | self._hooks[address] = callback
42 |
43 | ##############
44 | # Properties #
45 | ##############
46 |
47 | @property
48 | def _hooks(self):
49 | """dict: Dictionary of registered hooks."""
50 | return self.__hooks
51 |
52 | @_hooks.setter
53 | def _hooks(self, hooks):
54 | assert isinstance(hooks, dict), "Unexpected type for hooks of {}".format(type(hooks))
55 | self.__hooks = hooks
56 |
57 | @property
58 | def factory(self):
59 | return self.__factory
60 |
61 | @factory.setter
62 | def factory(self, factory) -> None:
63 | self.__factory = factory
64 |
65 | @property
66 | def file_name(self) -> str:
67 | """str: Name of the file that's being symbolically executed."""
68 | return self.__file_name
69 |
70 | @file_name.setter
71 | def file_name(self, file_name: str) -> None:
72 | file_name = os.path.abspath(file_name)
73 |
74 | # Make sure this is a real file.
75 | if not os.path.isfile(file_name):
76 | raise Exception("Not a valid file: {file_name:s}".format(file_name=file_name))
77 |
78 | self.__file_name = file_name
79 |
80 | from .Factory import Factory
81 |
--------------------------------------------------------------------------------
/pySym/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from .Project import Project
4 |
5 | """
6 | import ast
7 | import argparse
8 | import logging
9 | import symbolicExecutor
10 | from pySym import Colorer
11 |
12 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
13 | logger = logging.getLogger('main')
14 |
15 |
16 | parser = argparse.ArgumentParser(description='Symbolically Execute A Python Script.')
17 | parser.add_argument('script', type=str, nargs=1,
18 | help='Script file name')
19 | args = parser.parse_args()
20 |
21 | #print(args)
22 | script = args.script[0]
23 |
24 | # Load it
25 | logger.debug("Loading script {0}".format(script))
26 | with open(script,"r") as f:
27 | body = ast.parse(f.read()).body
28 |
29 | # Run it
30 | symbolicExecutor.runBody(body)
31 | """
32 |
--------------------------------------------------------------------------------
/pySym/ast_parse.py:
--------------------------------------------------------------------------------
1 | import ast
2 | from copy import copy
3 |
4 | def astCopy(self):
5 | new = self.__class__()
6 |
7 | #pypy has trouble writing to dict in this way :-(
8 | #new.__dict__ = {x: copy(getattr(self,x)) for x in self.__dict__}
9 |
10 | for attr in self.__dict__:
11 | setattr(new, attr, copy(getattr(self,attr)))
12 |
13 | return new
14 |
15 |
16 | for t in ['If','While','Compare','Return','For', "Assign", "AugAssign","BinOp"]:
17 | getattr(ast,t).__copy__ = astCopy
18 |
19 | def parse(s):
20 | """
21 | Parse string into python AST. Note that this needs to be separate due to hooking that I am performing on the objects.
22 | Returns: ast
23 | """
24 | return ast.parse(s)
25 |
--------------------------------------------------------------------------------
/pySym/pyObjectManager/decorators.py:
--------------------------------------------------------------------------------
1 | def as_clone(orig_func):
2 | def run_from_clone(self, *args, **kwargs):
3 | # Transparently run from clone object if we have one
4 | if self._clone is not None:
5 | return getattr(self._clone,orig_func.__name__)(*args, **kwargs)
6 |
7 | # We're not a clone, run the original
8 | else:
9 | return orig_func(self, *args, **kwargs)
10 |
11 | return run_from_clone
12 |
13 | # TODO: Probably should just make this all one decorator with an arg or something.
14 | def as_clone_property(orig_func):
15 | def run_from_clone(self, *args, **kwargs):
16 | # Transparently run from clone object if we have one
17 | if self._clone is not None:
18 | return getattr(self._clone,orig_func.__name__)
19 |
20 | # We're not a clone, run the original
21 | else:
22 | return orig_func(self, *args, **kwargs)
23 |
24 | return run_from_clone
25 |
--------------------------------------------------------------------------------
/pySym/pyPath.py:
--------------------------------------------------------------------------------
1 | import z3
2 | import ast
3 | import logging
4 | from .pyState import State
5 | from .Project import Project
6 | from prettytable import PrettyTable
7 | import sys
8 | from copy import copy
9 | from random import random
10 |
11 | logger = logging.getLogger("Path")
12 |
13 | class Path():
14 | """
15 | Defines a path of execution.
16 | """
17 |
18 | __slots__ = ['backtrace','state','source','error','__weakref__','__project']
19 |
20 | def __init__(self,path=None,backtrace=None,state=None,source=None,project=None):
21 | """
22 | (optional) path = list of sequential actions. Derived by ast.parse. Passed to state.
23 | (optional) backtrace = list of asts that happened before the current one
24 | (optional) state = State object for current path
25 | (optional) source = source code that we're looking at. This can make things prettier
26 | (optional) project = pySym project file associated with this group. This will be auto-filled.
27 | """
28 |
29 | self._project = project
30 | path = [] if path is None else path
31 | self.backtrace = [] if backtrace is None else backtrace
32 | self.state = State(path=path,project=self._project) if state is None else state
33 | self.source = source
34 |
35 | def step(self):
36 | """
37 | Move the current path forward by one step
38 | Note, this actually makes a copy/s and returns them. The initial path isn't modified.
39 | Returns: A list of paths or empty list if the path is done
40 | """
41 |
42 | # Step-it
43 | stateList = self.state.step()
44 |
45 | pathList = []
46 |
47 | for state in stateList:
48 | # New path. State should already be copied via state.step above.
49 | path = self.copy(state=state)
50 |
51 | # New state
52 | #path.state = state
53 |
54 | pathList.append(path)
55 |
56 | return pathList
57 |
58 | def printBacktrace(self):
59 | """
60 | Convinence function to print out what we've executed so far
61 | """
62 | source = self.source
63 | source = source.split("\n") if source != None else None
64 |
65 | table = PrettyTable(header=False,border=False,field_names=["lineno","line","element"])
66 | table.align = 'l'
67 |
68 | for inst in self.state.backtrace[::-1]:
69 | table.add_row([
70 | "Line {0}".format(inst.lineno),
71 | source[inst.lineno-1] if source != None else " ",
72 | inst])
73 |
74 | print(table)
75 |
76 | def copy(self, state=None):
77 | """
78 | Input:
79 | (optional) state == pyState object to use instead of copying the current state.
80 | Action:
81 | Create a copy of the current Path object
82 | Returns:
83 | Copy of the path
84 | """
85 | # TODO: Don't think i need to copy state in this...
86 | return Path(
87 | backtrace=copy(self.backtrace),
88 | state=self.state.copy() if state is None else state,
89 | source=copy(self.source),
90 | project=self._project
91 | )
92 |
93 | def __copy__(self):
94 | return self.copy()
95 |
96 | @property
97 | def _project(self):
98 | """pySym Project that this is associated with."""
99 | return self.__project
100 |
101 | @_project.setter
102 | def _project(self, project):
103 | assert isinstance(project, (Project, type(None))), "Invalid type for Project of {}".format(type(project))
104 | self.__project = project
105 |
--------------------------------------------------------------------------------
/pySym/pyState/Assert.py:
--------------------------------------------------------------------------------
1 | import logging
2 | logger = logging.getLogger("pyState:Assert")
3 |
4 | import z3
5 | import ast
6 | from . import Compare, BoolOp, ReturnObject
7 | from copy import copy
8 |
9 |
10 | def handle(state,element,ctx=None):
11 | """Attempt to handle the Python Assert element
12 |
13 | Parameters
14 | ----------
15 | state : pyState.State
16 | pyState.State object to handle this element under
17 | element : ast.Assert
18 | element from source to be handled
19 | ctx : int, optional
20 | `ctx` is an optional input to specify a context to be used
21 | when resolving this ast object
22 |
23 |
24 | Returns
25 | -------
26 | list
27 | list contains state objects either generated or discovered through
28 | handling this ast.
29 |
30 |
31 | This function handles calls to ast.Assert. It is not meant to be
32 | called manually via a user. Under the hood, it resolves the conitional
33 | arguments, then asserts the truth of that statement on the state.
34 |
35 |
36 | Example
37 | -------
38 | Example of ast.Assert is: assert x > 5
39 | """
40 |
41 | # element.msg -- what to evaluate if assertion is wrong. It doesn't have to be a string, just some expression.
42 |
43 | # Check what type of test this is
44 |
45 | # Example: assert 4 > 2
46 | if type(element.test) == ast.Compare:
47 | constraints = Compare.handle(state, element.test, ctx=ctx)
48 |
49 | else:
50 | raise Exception("Assert: Unknown test type of '{0}'".format(type(element.test)))
51 |
52 | """
53 | # Example: assert False
54 | # TODO: Need to add ast.NameConstant resolution to resolveObject before implementing this.
55 | elif type(element.test) == ast.NameConstant:
56 | import IPython
57 | IPython.embed()
58 | exit(0)
59 | """
60 |
61 | #elif type(element.test) == ast.UnaryOp:
62 | # trueConstraint = pyState.UnaryOp.handle(state, element.test)
63 | # # This returns pyObjectManager objects, need to resolve the
64 | # trueConstraint = [[x for x in constraint.state.assertions()][-1] for constraint in trueConstraint]
65 |
66 | # Resolve calls if we need to
67 | retObjs = [x.state for x in constraints if type(x) is ReturnObject]
68 | if len(retObjs) > 0:
69 | return retObjs
70 |
71 | state.addConstraint(*constraints)
72 |
73 | # Not waiting on anything, move forward
74 | state.path.pop(0)
75 |
76 | return [state]
77 |
--------------------------------------------------------------------------------
/pySym/pyState/BoolOp.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from .. import pyState
5 | from . import Compare
6 |
7 | logger = logging.getLogger("pyState:BoolOp")
8 |
9 | def _handle(state,op,values,ifSideConstraints=None):
10 | ifSideConstraints = [] if ifSideConstraints is None else ifSideConstraints
11 |
12 | # Loop through our requested checks
13 | for value in values:
14 | if type(value) is ast.Compare:
15 | ifSide = Compare.handle(state,value)
16 |
17 | # Normalize
18 | ifSide = [ifSide] if type(ifSide) is not list else ifSide
19 |
20 | # Resolve calls if we need to
21 | retObjs = [x for x in ifSide if type(x) is pyState.ReturnObject]
22 | if len(retObjs) > 0:
23 | return retObjs
24 |
25 |
26 | # Recursively build this
27 | v = values[:]
28 | v.pop(0)
29 | ret = []
30 | for i in ifSide:
31 | ret += _handle(state,op,v,ifSideConstraints + [i])
32 | return ret
33 |
34 | else:
35 | err = "handle: Don't know how to handle type '{0}' at line {1} column {2}".format(type(value),value.lineno,value.col_offset)
36 | logger.error(err)
37 | raise Exception(err)
38 |
39 | # Change the checks into a Z3 Expression
40 | if type(op) is ast.And:
41 | ifSide = z3.And(ifSideConstraints)
42 | return [ifSide]
43 |
44 | elif type(op) is ast.Or:
45 | ifSide = z3.Or(ifSideConstraints)
46 | return [ifSide]
47 |
48 | else:
49 | err = "handle: Don't know how to handle op type '{0}' at line {1} column {2}".format(type(op),element.lineno,element.col_offset)
50 | logger.error(err)
51 | raise Exception(err)
52 |
53 |
54 | def handle(state, element):
55 | """Attempt to handle the Python BoolOp element
56 |
57 | Parameters
58 | ----------
59 | state : pyState.State
60 | pyState.State object to handle this element under
61 | element : ast.BoolOp
62 | element from source to be handled
63 |
64 | Returns
65 | -------
66 | list
67 | list contains state objects either generated or discovered through
68 | handling this ast.
69 |
70 |
71 | This function handles calls to BoolOp. It is not meant to be called
72 | manually via a user.
73 |
74 |
75 | Example
76 | -------
77 | Example of ast.BoolOp is: x == 1 and y == 2
78 | """
79 |
80 | assert type(element) == ast.BoolOp
81 |
82 | op = element.op
83 |
84 | values = element.values
85 |
86 | return _handle(state,op,values)
87 |
--------------------------------------------------------------------------------
/pySym/pyState/Break.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from .. import pyState
5 |
6 | logger = logging.getLogger("pyState:Break")
7 |
8 | def handle(state,element):
9 | """Attempt to handle the Python Break element
10 |
11 | Parameters
12 | ----------
13 | state : pyState.State
14 | pyState.State object to handle this element under
15 | element : ast.Break
16 | element from source to be handled
17 |
18 | Returns
19 | -------
20 | list
21 | list contains state objects either generated or discovered through handling this ast.
22 |
23 |
24 | This function handles calls to Break. It is not meant to be called
25 | manually via a user. Under the hood, it simply pops off the call stack
26 | until a loop change is seen (i.e.: we've left the for loop)
27 |
28 |
29 | Example
30 | -------
31 | Example of ast.Break is: break
32 | """
33 |
34 | assert type(state) == pyState.State
35 | assert type(element) == ast.Break
36 |
37 | # We could be in a few levels of if/else statements. Pop back up to the loop
38 | while state.loop == None:
39 | state.popCallStack()
40 |
41 | # Good to go, pop out of our loop
42 | state.popCallStack()
43 |
44 | return [state]
45 |
46 |
--------------------------------------------------------------------------------
/pySym/pyState/Expr.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from .. import pyState
5 | from . import Call, ReturnObject
6 |
7 | logger = logging.getLogger("pyState:Expr")
8 |
9 | def handle(state,element):
10 | """Attempt to handle the Python Expr element
11 |
12 | Parameters
13 | ----------
14 | state : pyState.State
15 | pyState.State object to handle this element under
16 | element : ast.Expr
17 | element from source to be handled
18 |
19 |
20 | Returns
21 | -------
22 | list
23 | list contains state objects either generated or discovered through
24 | handling this ast.
25 |
26 |
27 | This function handles calls to ast.Expr. It is not meant to be called
28 | manually via a user.
29 |
30 |
31 | Example
32 | -------
33 | Example of ast.Expr is: test() (Note no assignment for call. This makes it
34 | an expression)
35 | """
36 |
37 | assert type(state) == pyState.State
38 | assert type(element) == ast.Expr
39 |
40 | # What is this expression?
41 | value = element.value
42 |
43 | if type(value) == ast.Call:
44 | ret = state.resolveObject(value)
45 |
46 | # Normalize
47 | ret = [ret] if type(ret) is not list else ret
48 |
49 | # Check for return object. Return all applicable
50 | retObjs = [x.state for x in ret if type(x) is pyState.ReturnObject]
51 | if len(retObjs) > 0:
52 | return retObjs
53 |
54 | states = [x for x in ret if type(x) is pyState.State]
55 |
56 | if len(states) > 0:
57 | return states
58 |
59 | # Don't really care about the return object for now... Maybe later?
60 | # A str expression is just a multi-line comment. Ignore
61 | elif type(value) in [ReturnObject, ast.Str]:
62 | pass
63 |
64 | else:
65 | err = "Expr: Don't know how to handle expr type {0} at line {1} col {2}".format(type(value),value.lineno,value.col_offset)
66 | logger.error(err)
67 | raise Exception(err)
68 |
69 |
70 | state.path.pop(0)
71 | return [state]
72 |
73 |
--------------------------------------------------------------------------------
/pySym/pyState/FunctionDef.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from .. import pyState
5 |
6 | logger = logging.getLogger("pyState:FunctionDef")
7 |
8 | def handle(state,element):
9 | """Attempt to handle the Python FunctionDef element
10 |
11 | Parameters
12 | ----------
13 | state : pyState.State
14 | pyState.State object to handle this element under
15 | element : ast.FunctionDef
16 | element from source to be handled
17 |
18 |
19 | Returns
20 | -------
21 | list
22 | list contains state objects either generated or discovered through
23 | handling this ast.
24 |
25 |
26 | This function handles calls to ast.FunctionDef. It is not meant to be called
27 | manually via a user. Under the hood, it registers this function with the
28 | `state` object so that when it's referenced later it can be found.
29 |
30 |
31 | Example
32 | -------
33 | Example of ast.FunctionDef is: def test():
34 | """
35 |
36 | assert type(state) == pyState.State
37 | assert type(element) == ast.FunctionDef
38 |
39 | state.registerFunction(element)
40 |
41 | # Pop instruction
42 | state.path.pop(0)
43 |
44 | # Return state
45 | return [state]
46 |
--------------------------------------------------------------------------------
/pySym/pyState/GeneratorExp.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from ..pyObjectManager.Int import Int
5 | from ..pyObjectManager.Real import Real
6 | from ..pyObjectManager.BitVec import BitVec
7 | from ..pyObjectManager.List import List
8 | from .. import pyState
9 | from . import ListComp
10 |
11 | logger = logging.getLogger("pyState:GeneratorExp")
12 |
13 | #import astunparse
14 |
15 |
16 | def handle(state,element,ctx=None):
17 | """Attempt to handle the Python GeneratorExp element
18 |
19 | Parameters
20 | ----------
21 | state : pyState.State
22 | pyState.State object to handle this element under
23 | element : ast.GeneratorExp
24 | element from source to be handled
25 |
26 |
27 | Returns
28 | -------
29 | list
30 | list contains state objects either generated or discovered through
31 | handling this ast.
32 |
33 |
34 | This function handles calls to ast.GeneratorExp. It is not meant to be
35 | called manually via a user. Under the hood, it converts the generator
36 | expression into a list comprehension and calls the handler for list
37 | comprehension.
38 |
39 |
40 | Example
41 | -------
42 | Example of ast.GeneratorExp is: x for x in [1,2,3] (note it's not inside
43 | List Comprehension brackets)
44 | """
45 |
46 | assert type(element) is ast.GeneratorExp
47 |
48 | ctx = state.ctx if ctx is None else ctx
49 |
50 | # NOTE: Maybe there are cases where we don't want the GeneratorExp to be turned into ListComp?
51 |
52 | # Create a skelleton ListComp
53 | listComp = ast.parse("[x for x in []]").body[0].value
54 |
55 | # Pop in our generator
56 | listComp.generators = element.generators
57 |
58 | # Pop in our element
59 | listComp.elt = element.elt
60 |
61 | # Make the switch
62 | pyState.replaceObjectWithObject(state.path[0],element,listComp)
63 |
64 | #print(astunparse.unparse(element))
65 | #print(astunparse.unparse(listComp))
66 |
67 | # Call ListComp to handle this
68 | return ListComp.handle(state,listComp,ctx=ctx)
69 |
70 |
71 |
--------------------------------------------------------------------------------
/pySym/pyState/Pass.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from .. import pyState
5 |
6 | logger = logging.getLogger("pyState:Pass")
7 |
8 | def handle(state,element):
9 | """Attempt to handle the Python Pass element
10 |
11 | Parameters
12 | ----------
13 | state : pyState.State
14 | pyState.State object to handle this element under
15 | element : ast.Pass
16 | element from source to be handled
17 |
18 |
19 | Returns
20 | -------
21 | list
22 | list contains state objects either generated or discovered through
23 | handling this ast.
24 |
25 |
26 | This function handles calls to ast.Pass. It is not meant to be
27 | called manually via a user. Under the hood, it very simply pops off the
28 | current instruction and returns the updated state object as a list.
29 |
30 |
31 | Example
32 | -------
33 | Example of ast.Pass is: pass
34 | """
35 |
36 |
37 | state.path.pop(0)
38 |
39 | return [state]
40 |
--------------------------------------------------------------------------------
/pySym/pyState/Return.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from .. import pyState
5 |
6 | logger = logging.getLogger("pyState:Return")
7 |
8 | def handle(state,element):
9 | """Attempt to handle the Python Return element
10 |
11 | Parameters
12 | ----------
13 | state : pyState.State
14 | pyState.State object to handle this element under
15 | element : ast.Return
16 | element from source to be handled
17 |
18 |
19 | Returns
20 | -------
21 | list
22 | list contains state objects either generated or discovered through
23 | handling this ast.
24 |
25 |
26 | This function handles calls to ast.Return. It is not meant to be
27 | called manually via a user. Under the hood, it resolves the return element,
28 | sets the ReturnObject, and updates the state.
29 |
30 |
31 | Example
32 | -------
33 | Example of ast.Return is: return x
34 | """
35 |
36 |
37 | assert type(state) == pyState.State
38 | assert type(element) == ast.Return
39 |
40 | ret = state.Return(element)
41 |
42 | logger.debug("handle: ret value = {0}".format(ret))
43 |
44 | # Normalize
45 | ret = [ret] if type(ret) is not list else ret
46 |
47 | # Check for return object. Return all applicable
48 | retObjs = [x.state for x in ret if type(x) is pyState.ReturnObject]
49 | if len(retObjs) > 0:
50 | return retObjs
51 |
52 | # Asserting 1 thing to return for now
53 | assert len(ret) == 1
54 | obj = ret[0]
55 |
56 | state = obj.state if obj is not None else state
57 |
58 | # Pop callstacks until we change context
59 | leavingCtx = state.ctx
60 |
61 | # Pop until we've left
62 | while leavingCtx == state.ctx:
63 |
64 | state.popCallStack()
65 |
66 | return [state]
67 |
68 |
--------------------------------------------------------------------------------
/pySym/pyState/UnaryOp.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from .. import pyState
5 | from ..pyObjectManager.Int import Int
6 | from ..pyObjectManager.Real import Real
7 | from ..pyObjectManager.BitVec import BitVec
8 |
9 | logger = logging.getLogger("pyState:UnaryOp")
10 |
11 | def handle(state,element,ctx=None):
12 | """Attempt to handle the Python UnaryOp element
13 |
14 | Parameters
15 | ----------
16 | state : pyState.State
17 | pyState.State object to handle this element under
18 | element : ast.UnaryOp
19 | element from source to be handled
20 | ctx : int , optional
21 | Context to resolve this UnaryOp in (default is current context)
22 |
23 |
24 | Returns
25 | -------
26 | list
27 | list contains state objects either generated or discovered through
28 | handling this ast.
29 |
30 |
31 | This function handles calls to ast.UnaryOp. It is not meant to be
32 | called manually via a user.
33 |
34 |
35 | Example
36 | -------
37 | Example of ast.UnaryOp is: not True
38 | """
39 |
40 | ctx = state.ctx if ctx is None else ctx
41 |
42 | assert type(state) == pyState.State
43 | assert type(element) == ast.UnaryOp
44 |
45 | op = element.op
46 | targets = state.resolveObject(element.operand)
47 |
48 | ret = []
49 |
50 | for target in targets:
51 |
52 | # Use the target's state
53 | state = target.state
54 |
55 | if type(target) not in [Int, Real, BitVec]:
56 | err = "handle: unable to resolve UnaryOp target type '{0}'".format(type(target))
57 | logger.error(err)
58 | raise Exception(err)
59 |
60 | # Get a new variable
61 | t,args = pyState.duplicateSort(target)
62 | newVar = state.getVar("tempUnaryOp",varType=t,kwargs=args)
63 | newVar.increment()
64 |
65 | if type(op) == ast.USub:
66 | # Optimize if we can
67 | if target.isStatic():
68 | newVar.setTo(target.getValue() * -1)
69 | else:
70 | state.addConstraint(newVar.getZ3Object() == -target.getZ3Object())
71 |
72 | elif type(op) == ast.UAdd:
73 | #state.addConstraint(newVar.getZ3Object() == target.getZ3Object())
74 | newVar.setTo(target)
75 |
76 | elif type(op) == ast.Not:
77 | # TODO: Verify functionality here... Should be able to optimize like I did with the other two, but need to check how "Not" is being dealt with
78 | state.addConstraint(newVar.getZ3Object() == z3.Not(target.getZ3Object()))
79 |
80 | elif type(op) == ast.Invert:
81 | err = "handle: Invert not implemented yet"
82 | logger.error(err)
83 | raise Exception(err)
84 |
85 | else:
86 | # We really shouldn't get here...
87 | err = "handle: {0} not implemented yet".format(type(op))
88 | logger.error(err)
89 | raise Exception(err)
90 |
91 | ret.append(newVar.copy())
92 |
93 | return ret
94 |
--------------------------------------------------------------------------------
/pySym/pyState/While.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import z3
3 | import ast
4 | from . import Compare, ReturnObject
5 | from copy import copy
6 | import pickle
7 |
8 | logger = logging.getLogger("pyState:While")
9 |
10 | def _handle(stateIf,stateElse,element,ifConstraint):
11 | # Add the constraints
12 | if type(ifConstraint) is not bool or ifConstraint != True:
13 | stateIf.addConstraint(ifConstraint)
14 | if type(ifConstraint) is not bool or ifConstraint == True:
15 | stateElse.addConstraint(z3.Not(ifConstraint))
16 |
17 | # Check if statement. We'll have at least one instruction here, so treat this as a call
18 | # Saving off the current path so we can return to it and pick up at the next instruction
19 | cs = copy(stateIf.path)
20 | # Only push our stack if it's not empty
21 | if len(cs) > 0:
22 | stateIf.pushCallStack(path=cs)
23 |
24 | # Our new path becomes the inside of the if statement
25 | stateIf.path = element.body
26 |
27 | # If state should get a copy of the loop we're now in
28 | stateIf.loop = copy(element)
29 |
30 | # Update the else's path
31 | # Check if there is an else path we need to take
32 | #if len(element.orelse) > 0:
33 | cs = copy(stateElse.path)
34 | if len(cs) > 0:
35 | stateElse.pushCallStack(path=cs)
36 |
37 | # else side should be done with the loop
38 | stateElse.loop = None
39 |
40 | stateElse.path = element.orelse
41 |
42 | return [stateIf, stateElse]
43 |
44 |
45 | def handle(state,element):
46 | """Attempt to handle the Python While element
47 |
48 | Parameters
49 | ----------
50 | state : pyState.State
51 | pyState.State object to handle this element under
52 | element : ast.While
53 | element from source to be handled
54 |
55 |
56 | Returns
57 | -------
58 | list
59 | list contains state objects either generated or discovered through
60 | handling this ast.
61 |
62 |
63 | This function handles calls to ast.While. It is not meant to be
64 | called manually via a user.
65 |
66 |
67 | Example
68 | -------
69 | Example of ast.While is: while x < 10:
70 | """
71 |
72 |
73 | # While is basically a repeated If statement, we want to take both sides
74 |
75 | stateIf = state
76 | ret = []
77 |
78 | # Check what type of test this is
79 | if type(element.test) == ast.Compare:
80 | # Try to handle the compare
81 | ifConstraint = Compare.handle(stateIf,element.test)
82 |
83 | else:
84 | err = "handle: I don't know how to handle type {0}".format(type(element.test))
85 | logger.error(err)
86 | raise Exception(err)
87 |
88 | # Normalize
89 | ifConstraint = ifConstraint if type(ifConstraint) is list else [ifConstraint]
90 |
91 | # See if we need to pass back a call
92 | retObjs = [x.state for x in ifConstraint if type(x) is ReturnObject]
93 | if len(retObjs) > 0:
94 | return retObjs
95 |
96 | # If we're good to go, pop the instruction
97 | stateIf.path.pop(0)
98 |
99 | # Loop through possible constraints
100 | for constraint in ifConstraint:
101 |
102 | ret += _handle(stateIf.copy(),stateIf.copy(),element,constraint)
103 |
104 | return ret
105 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/List/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bannsec/pySym/497b5d84e5e360ea57ceaf26d477d3fad1d4e6c8/pySym/pyState/functions/List/__init__.py
--------------------------------------------------------------------------------
/pySym/pyState/functions/List/append.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from ....pyObjectManager.List import List
3 | from ....pyObjectManager.Int import Int
4 | from ....pyObjectManager.Real import Real
5 | from ....pyObjectManager.BitVec import BitVec
6 | from ....pyObjectManager.String import String
7 | from .... import pyState
8 | from copy import copy
9 |
10 | logger = logging.getLogger("pyState:SimFunction:List:append")
11 |
12 |
13 | def handle(state,call,var,ctx=None):
14 | """
15 | Append var to list
16 | """
17 | ctx = ctx if ctx is not None else state.ctx
18 |
19 | #print("Attempting to append {0} of type {1} from CTX {2}".format(var,type(var),ctx))
20 |
21 | # Resolve what we're going to be appending
22 | varList = state.resolveObject(var,ctx=ctx)
23 |
24 | # If we're waiting on a symbolic call, return
25 | retObjs = [x for x in varList if type(x) is pyState.ReturnObject]
26 | if len(retObjs) > 0:
27 | return retObjs
28 |
29 | ret = []
30 |
31 | for var in varList:
32 | s = var.state.copy()
33 |
34 | s.path.pop(0)
35 |
36 | # If we are given a List object, use that as root
37 | if type(call) is List:
38 | root = call
39 |
40 | # Resolve Root
41 | else:
42 | root = s.resolveObject(call.func.value,ctx=ctx)
43 |
44 | assert len(root) == 1
45 | root = root.pop()
46 |
47 | assert type(root) is List
48 |
49 | # Append it
50 | root.append(copy(var))
51 |
52 | # Add this to our returns
53 | retObj = pyState.ReturnObject(1)
54 | retObj.state = s
55 |
56 | ret.append(retObj)
57 |
58 | return ret
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/List/clear.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from ....pyObjectManager.List import List
3 | from ....pyObjectManager.Int import Int
4 | from ....pyObjectManager.Real import Real
5 | from ....pyObjectManager.BitVec import BitVec
6 | from ....pyObjectManager.String import String
7 | from .... import pyState
8 |
9 | logger = logging.getLogger("pyState:SimFunction:List:clear")
10 |
11 |
12 | def handle(state,call,ctx=None):
13 | """
14 | Clear list
15 | """
16 | ctx = ctx if ctx is not None else state.ctx
17 |
18 | # The "l" in "l.clear()"
19 | roots = state.resolveObject(call.func.value,ctx=ctx)
20 |
21 | # If we're waiting on a symbolic call (that'd be weird..), return
22 | retObjs = [x for x in roots if type(x) is pyState.ReturnObject]
23 | if len(retObjs) > 0:
24 | return retObjs
25 |
26 | # Not sure when we'd ever have multiple...
27 | assert len(roots) == 1
28 |
29 | root = roots[0]
30 |
31 | root.state.path.pop(0)
32 |
33 | root.increment()
34 | root.variables = []
35 |
36 | return [root.state]
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/List/insert.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from ....pyObjectManager.List import List
3 | from ....pyObjectManager.Int import Int
4 | from ....pyObjectManager.Real import Real
5 | from ....pyObjectManager.BitVec import BitVec
6 | from ....pyObjectManager.String import String
7 | from .... import pyState
8 | from copy import copy
9 |
10 | logger = logging.getLogger("pyState:SimFunction:List:insert")
11 |
12 |
13 | def handle(state,call,index,object,ctx=None):
14 | """
15 | Insert object in a list at index
16 | """
17 | ctx = ctx if ctx is not None else state.ctx
18 |
19 | # Resolve index
20 | indexList = state.resolveObject(index,ctx=ctx)
21 |
22 | # If we're waiting on a symbolic call, return
23 | retObjs = [x for x in indexList if type(x) is pyState.ReturnObject]
24 | if len(retObjs) > 0:
25 | return retObjs
26 |
27 | # Resolve what we're going to be inserting
28 | objList = state.resolveObject(object,ctx=ctx)
29 |
30 | # If we're waiting on a symbolic call, return
31 | retObjs = [x for x in objList if type(x) is pyState.ReturnObject]
32 | if len(retObjs) > 0:
33 | return retObjs
34 |
35 | ret = []
36 |
37 | for obj in objList:
38 |
39 | for index in indexList:
40 |
41 | # Only static index for now
42 | if not index.isStatic():
43 | err = "List.insert called with symbolic index. This is not supported right now."
44 | logger.error(err)
45 | raise Exception(err)
46 |
47 | s = obj.state.copy()
48 |
49 | s.path.pop(0)
50 |
51 | # Resolve Root
52 | root = s.resolveObject(call.func.value,ctx=ctx)
53 |
54 | assert len(root) == 1, "Unhandled root of length {}".format(len(root))
55 | root = root.pop()
56 |
57 | assert type(root) is List, "Unexpected root type of {}".format(type(root))
58 |
59 | # Append it
60 | root.insert(index, copy(obj))
61 |
62 | # Add this to our returns
63 | retObj = pyState.ReturnObject(1)
64 | retObj.state = s
65 |
66 | ret.append(retObj)
67 |
68 | return ret
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/String/index.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from ....pyObjectManager.List import List
3 | from ....pyObjectManager.Int import Int
4 | from ....pyObjectManager.Real import Real
5 | from ....pyObjectManager.BitVec import BitVec
6 | from ....pyObjectManager.Char import Char
7 | from ....pyObjectManager.String import String
8 | import ast
9 |
10 | logger = logging.getLogger("pyState:SimFunction:String.index")
11 |
12 |
13 | def handle(state,call,sub,start=None,end=None,ctx=None):
14 | """
15 | Determine location of char in string.
16 | """
17 | ctx = ctx if ctx is not None else state.ctx
18 |
19 | # The root (i.e.: "s" in s.index())
20 | root = state.resolveObject(call.func.value,ctx=ctx)
21 |
22 | assert len(root) == 1
23 |
24 | root = root.pop()
25 |
26 | assert type(root) is String
27 |
28 | # Resolve the vars
29 | subs = state.resolveObject(sub,ctx=ctx)
30 |
31 | for sub in subs:
32 | # If we're indexing a Char, just change it into a String
33 | if type(sub) is Char:
34 | c = sub
35 | sub = String("tempIndex",1,state=sub.state)
36 | sub.variables.append(c)
37 | subs[subs.index(c)] = sub
38 |
39 |
40 | assert min([type(sub) is String for sub in subs]) == True
41 |
42 | start = state.resolveObject(start,ctx=ctx) if start is not None else None
43 | end = state.resolveObject(end,ctx=ctx) if end is not None else None
44 |
45 | if type(start) not in [int,type(None)]:
46 | if not start.isStatic():
47 | err = "handle: Don't know how to handle appending type {0}".format(type(var))
48 | logger.error(err)
49 | raise Exception(err)
50 | start = start.getValue()
51 |
52 | if type(end) not in [int,type(None)]:
53 | if not end.isStatic():
54 | err = "handle: Don't know how to handle appending type {0}".format(type(var))
55 | logger.error(err)
56 | raise Exception(err)
57 | end = end.getValue()
58 |
59 | # Get the substring
60 | if start is None:
61 | start = 0
62 |
63 | if end is None:
64 | end = len(root)
65 |
66 | subStr = root[start:end]
67 | ret = []
68 |
69 | # Move the size window through the input
70 | for i in range(0,len(subStr) - len(sub) + 1):
71 | # If it is possible to have this index here, add it
72 | if subStr[i:i+len(sub)].canBe(sub):
73 | ret.append(Int('tempStrIndex',1,value=i,state=state))
74 |
75 | # If this is the only possible place, we must stop
76 | if subStr[i:i+len(sub)].mustBe(sub):
77 | break
78 |
79 | return ret
80 |
81 |
82 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/String/join.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from ....pyObjectManager.List import List
3 | from ....pyObjectManager.Int import Int
4 | from ....pyObjectManager.Real import Real
5 | from ....pyObjectManager.BitVec import BitVec
6 | from ....pyObjectManager.Char import Char
7 | from ....pyObjectManager.String import String
8 | import ast
9 | from .... import pyState
10 |
11 | logger = logging.getLogger("pyState:SimFunction:String.join")
12 |
13 |
14 | def handle(state,call,elem,ctx=None):
15 | """
16 | Simulate Python's join string method
17 | """
18 | ctx = ctx if ctx is not None else state.ctx
19 |
20 | # The root (i.e.: "s" in s.join())
21 | root = state.resolveObject(call.func.value,ctx=ctx)
22 |
23 | assert len(root) == 1
24 | root = root.pop()
25 |
26 | assert type(root) is String
27 |
28 | # Resolve the elem
29 | elems = state.resolveObject(elem,ctx=ctx)
30 |
31 | elems = elems if type(elems) is list else [elems]
32 |
33 | # If we're waiting on a symbolic call, return
34 | retObjs = [x for x in elems if type(x) is pyState.ReturnObject]
35 | if len(retObjs) > 0:
36 | return retObjs
37 |
38 | ret = []
39 |
40 | for elem in elems:
41 |
42 | if type(elem) is not List:
43 | err = "handle: Don't know how to handle non-List join iterators"
44 | logger.error(err)
45 | raise Exception(err)
46 |
47 |
48 | # Get new string
49 | newString = state.getVar('tempStrJoin',ctx=1,varType=String)
50 | newString.increment()
51 |
52 | # Loop through elem values
53 | for item in elem:
54 | if type(item) is String:
55 | newString.variables += item.variables + root.variables
56 | elif type(item) is Char:
57 | newString.variables += [item.variable] + root.variables
58 | else:
59 | err = "handle: Don't know how to handle type {0}".format(type(item))
60 | logger.error(err)
61 | raise Exception(err)
62 |
63 | if len(root) > 0:
64 | # Remove the excess chars that may have built up
65 | newString = newString[:-len(root)]
66 |
67 | ret.append(newString.copy())
68 |
69 | return ret
70 |
71 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/String/zfill.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from ....pyObjectManager.List import List
3 | from ....pyObjectManager.Int import Int
4 | from ....pyObjectManager.Real import Real
5 | from ....pyObjectManager.BitVec import BitVec
6 | from ....pyObjectManager.Char import Char
7 | from ....pyObjectManager.String import String
8 | import ast
9 | from .... import pyState
10 |
11 | logger = logging.getLogger("pyState:SimFunction:String.zfill")
12 |
13 |
14 | def handle(state,call,width,ctx=None):
15 | """
16 | Simulate Python's zfill string method
17 | """
18 | ctx = ctx if ctx is not None else state.ctx
19 |
20 | # The root (i.e.: "s" in s.zfill())
21 | root = state.resolveObject(call.func.value,ctx=ctx)
22 |
23 | assert len(root) == 1
24 | root = root.pop()
25 |
26 | assert type(root) is String
27 |
28 | # Resolve the width
29 | widths = state.resolveObject(width,ctx=ctx)
30 |
31 | # Resolve calls if we need to
32 | retObjs = [x for x in widths if type(x) is pyState.ReturnObject]
33 | if len(retObjs) > 0:
34 | return retObjs
35 |
36 | ret = []
37 |
38 | for width in widths:
39 |
40 | # TODO: Add symbolic width capability
41 | if not width.isStatic():
42 | err = "handle: Don't know how to handle non static width"
43 | logger.error(err)
44 | raise Exception(err)
45 |
46 | # TODO: Add symbolic string capability
47 | if not root.isStatic():
48 | err = "handle: Don't know how to handle symbolic string"
49 | logger.error(err)
50 | raise Exception(err)
51 |
52 | # Get new str
53 | newString = state.getVar('tempZfillStr',ctx=1,varType=String)
54 | newString.increment()
55 |
56 | # Resolve the width
57 | width = width.getValue()
58 |
59 | # zfill will not truncate
60 | newString.setTo(root,clear=True)
61 |
62 | # If we're already at our length, just return
63 | if len(newString) >= width:
64 | ret.append(newString.copy())
65 | continue
66 |
67 | # Add as many "0"s as needed
68 | while len(newString) < width:
69 | # Create the new Char
70 | c = state.getVar('tempCharZfill',ctx=1,varType=Char)
71 | c.increment()
72 | # Set it
73 | c.setTo('0')
74 | # Insert it
75 | newString.variables.insert(0,c.copy())
76 |
77 | ret.append(newString.copy())
78 |
79 | return ret
80 |
81 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/__init__.py:
--------------------------------------------------------------------------------
1 | # blerg
2 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/abs.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ...pyObjectManager.Real import Real
3 | from ...pyObjectManager.BitVec import BitVec
4 | from ...pyObjectManager.String import String
5 | from ... import pyState
6 | import logging
7 | import z3
8 |
9 | logger = logging.getLogger("pyState:functions:abs")
10 |
11 |
12 | def handle(state,call,obj,ctx=None):
13 | """
14 | Simulate abs funcion
15 | """
16 | ctx = ctx if ctx is not None else state.ctx
17 |
18 | # Resolve the object
19 | objs = state.resolveObject(obj,ctx=ctx)
20 |
21 | # Resolve calls if we need to
22 | retObjs = [x for x in objs if type(x) is pyState.ReturnObject]
23 | if len(retObjs) > 0:
24 | return retObjs
25 |
26 | retList = []
27 |
28 | # Loop through all possible inputs
29 | for obj in objs:
30 |
31 | s = obj.state.copy()
32 |
33 | obj.state = s
34 |
35 | if type(obj) not in [Int, Real, BitVec]:
36 | err = "handle: This shouldn't happen. Possibly a target program bug? Got obj type {0}".format(type(obj))
37 | logger.error(err)
38 | raise Exception(err)
39 |
40 | oldObj = obj.copy()
41 |
42 | obj.increment()
43 | newObj = obj
44 |
45 | # Take shortcut if we know these values are static-ish
46 | if oldObj.isStatic():
47 | newObj.setTo(abs(oldObj.getValue()))
48 |
49 | else:
50 |
51 | # Add a little z3 If statement to mimic abs() call
52 | s.addConstraint(
53 | newObj.getZ3Object() ==
54 | z3.If(
55 | oldObj.getZ3Object() > 0,
56 | oldObj.getZ3Object(),
57 | -oldObj.getZ3Object()
58 | )
59 | )
60 |
61 | retList.append(obj.copy())
62 |
63 | # Return all options
64 | return retList
65 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/bin.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ...pyObjectManager.Real import Real
3 | from ...pyObjectManager.BitVec import BitVec
4 | from ...pyObjectManager.String import String
5 | from ... import pyState
6 | import logging
7 |
8 | logger = logging.getLogger("pyState:functions:bin")
9 |
10 |
11 | def handle(state,call,obj,ctx=None):
12 | """
13 | Simulate bin funcion
14 | """
15 | ctx = ctx if ctx is not None else state.ctx
16 |
17 | # Resolve the object
18 | objs = state.resolveObject(obj,ctx=ctx)
19 |
20 | # Normalize
21 | objs = [objs] if type(objs) is not list else objs
22 |
23 | # Resolve calls if we need to
24 | retObjs = [x for x in objs if type(x) is pyState.ReturnObject]
25 | if len(retObjs) > 0:
26 | return retObjs
27 |
28 | retList = []
29 |
30 | # Loop through all possible inputs
31 | for obj in objs:
32 |
33 | if type(obj) not in [Int, Real, BitVec]:
34 | err = "handle: This shouldn't happen. Possibly a target program bug? Got obj type {0}".format(type(obj))
35 | logger.error(err)
36 | raise Exception(err)
37 |
38 | # Only dealing with concrete values for now.
39 | if obj.isStatic():
40 | val = obj.getValue()
41 | ret = state.getVar("tmpStrVal",ctx=1,varType=String)
42 | ret.increment()
43 | ret.setTo(bin(val),clear=True)
44 |
45 | # TODO: Deal with symbolic values (returning list of possibilities)
46 | else:
47 | err = "handle: Don't know how to handle symbolic ints for now"
48 | logger.error(err)
49 | raise Exception(err)
50 |
51 |
52 | retList.append(ret.copy())
53 |
54 | # Return all options
55 | return retList
56 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/chr.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ...pyObjectManager.Real import Real
3 | from ...pyObjectManager.BitVec import BitVec
4 | from ...pyObjectManager.String import String
5 | from ...pyObjectManager.List import List
6 | import logging
7 | from ... import pyState
8 |
9 | logger = logging.getLogger("pyState:functions:chr")
10 |
11 | import z3
12 |
13 | def handle(state,call,obj,ctx=None):
14 | """
15 | Simulate chr funcion
16 | """
17 | ctx = ctx if ctx is not None else state.ctx
18 |
19 | # Resolve the object
20 | objs = state.resolveObject(obj,ctx=ctx)
21 |
22 | # Normalize
23 | objs = [objs] if type(objs) is not list else objs
24 |
25 | # Resolve calls if we need to
26 | retObjs = [x for x in objs if type(x) is pyState.ReturnObject]
27 | if len(retObjs) > 0:
28 | return retObjs
29 |
30 | # Loop through our input
31 | retList = []
32 | for obj in objs:
33 |
34 | # This is probably a script problem, not us
35 | # TODO: Handle sending Exceptions back to the program, not us.
36 | if type(obj) is not Int:
37 | err = "handle: Invalid param for chr type {0}".format(type(obj))
38 | raise Exception(err)
39 |
40 | # Single value
41 | if obj.isStatic():
42 |
43 | # Is this integer too large or too small?
44 | obj_value = int(obj)
45 | if obj_value < 0 or obj_value >= 0x110000:
46 | err = "handle: Invalid integer value for chr of {0}. Needs to be in range(0x110000)".format(obj_value)
47 | raise Exception(err)
48 |
49 | # TODO: Figure out how to handle this case...
50 | elif obj_value > 0xff:
51 | err = "handle: Not sure how to handle chr(>0xff) right now..."
52 | raise Exception(err)
53 |
54 |
55 | # Grab a new var to work with
56 | ret = obj.state.getVar("tmpChrVal",ctx=1,varType=String,kwargs={'increment':True})
57 | ret.setTo(chr(int(obj)),clear=True)
58 |
59 | # If it's symbolic, we need help from z3
60 | else:
61 | # Grab a new var to work with
62 | ret = obj.state.getVar("tmpChrVal",ctx=1,varType=String,kwargs={'increment':True})
63 | ret.setTo(obj, clear=True)
64 |
65 | retList.append(ret.copy())
66 |
67 | return retList
68 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/hex.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ...pyObjectManager.Real import Real
3 | from ...pyObjectManager.BitVec import BitVec
4 | from ...pyObjectManager.String import String
5 | from ...pyObjectManager.List import List
6 | import logging
7 | from ... import pyState
8 |
9 | logger = logging.getLogger("pyState:functions:hex")
10 |
11 |
12 | def handle(state,call,obj,ctx=None):
13 | """
14 | Simulate hex funcion
15 | """
16 | ctx = ctx if ctx is not None else state.ctx
17 |
18 | # Resolve the object
19 | objs = state.resolveObject(obj,ctx=ctx)
20 |
21 | # Normalize
22 | objs = [objs] if type(objs) is not list else objs
23 |
24 | # Resolve calls if we need to
25 | retObjs = [x for x in objs if type(x) is pyState.ReturnObject]
26 | if len(retObjs) > 0:
27 | return retObjs
28 |
29 | # Loop through our input
30 | retList = []
31 |
32 | for obj in objs:
33 |
34 | # This is probably a script problem, not us
35 | if type(obj) not in [Int, BitVec]:
36 | err = "handle: Invalid param for hex type {0}".format(type(obj))
37 | logger.error(err)
38 | raise Exception(err)
39 |
40 | # Only dealing with concrete values for now.
41 | if obj.isStatic():
42 | ret = state.getVar("tmpHexVal",ctx=1,varType=String)
43 | ret.increment()
44 | ret.setTo(hex(obj.getValue()),clear=True)
45 |
46 | # TODO: Deal with symbolic values (returning list of possibilities)
47 | else:
48 | err = "handle: Don't know how to handle symbolic for now"
49 | logger.error(err)
50 | raise Exception(err)
51 |
52 |
53 | retList.append(ret.copy())
54 |
55 | return retList
56 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/int.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ...pyObjectManager.Real import Real
3 | from ...pyObjectManager.BitVec import BitVec
4 | from ...pyObjectManager.String import String
5 | from ...pyObjectManager.Char import Char
6 | import logging
7 | from ... import pyState
8 |
9 | logger = logging.getLogger("pyState:functions:int")
10 |
11 |
12 | def handle(state,call,obj,base=10,ctx=None):
13 | """
14 | Simulate int funcion
15 | """
16 | ctx = ctx if ctx is not None else state.ctx
17 |
18 | # Resolve the object
19 | objs = state.resolveObject(obj,ctx=ctx)
20 |
21 | # Resolve calls if we need to
22 | retObjs = [x for x in objs if type(x) is pyState.ReturnObject]
23 | if len(retObjs) > 0:
24 | return retObjs
25 |
26 | # Loop through inputs
27 | retList = []
28 |
29 | for obj in objs:
30 |
31 | if type(obj) not in [Int, Real, BitVec, String, Char]:
32 | err = "handle: Don't know how to handle type {0}".format(type(obj))
33 | logger.error(err)
34 | raise Exception(err)
35 |
36 | # Check up-front types for int. Catch these issues
37 | if type(obj) in [Int, Real, BitVec] and type(base) is not int:
38 | err = "handle: Cannot use base variable when using non-string object".format(type(obj))
39 | logger.error(err)
40 | raise Exception(err)
41 |
42 | # Resolve base
43 | base = [base] if type(base) is int else obj.state.resolveObject(base,ctx=ctx)
44 |
45 | # TODO: Deal with extra states later...
46 | assert len(base) == 1
47 | base = base.pop()
48 |
49 | # Only dealing with concrete values for now.
50 | if obj.isStatic() and (type(base) is int or base.isStatic()):
51 | val = obj.getValue()
52 | ret = state.getVar("tmpIntVal",ctx=1,varType=Int)
53 | ret.increment()
54 | base = base if type(base) is int else base.getValue()
55 |
56 | # int() doesn't like base set for non-strings
57 | if type(val) is str:
58 | ret.setTo(int(val,base))
59 | else:
60 | ret.setTo(int(val))
61 |
62 |
63 | # TODO: Deal with symbolic values (returning list of possibilities)
64 | else:
65 | print("any",state.any_n_real(obj,10))
66 | print(state.solver)
67 | print(obj.getZ3Object())
68 | print(state.solver.check())
69 | err = "handle: Don't know how to handle symbolic ints for now"
70 | logger.error(err)
71 | raise Exception(err)
72 |
73 |
74 | retList.append(ret.copy())
75 |
76 | return retList
77 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/len.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ... import pyState
3 |
4 | def handle(state,call,obj,ctx=None):
5 | """
6 | Simulate len funcion
7 | """
8 | ctx = ctx if ctx is not None else state.ctx
9 |
10 | # Resolve the object
11 | objs = state.resolveObject(obj,ctx=ctx)
12 |
13 | # Normalize
14 | objs = [objs] if type(objs) is not list else objs
15 |
16 | # Resolve calls if we need to
17 | retObjs = [x for x in objs if type(x) is pyState.ReturnObject]
18 | if len(retObjs) > 0:
19 | return retObjs
20 |
21 | # Loop through input
22 |
23 | ret = []
24 |
25 | for obj in objs:
26 |
27 | # Just calling the length function on the object..
28 | l = len(obj)
29 |
30 | i = state.getVar("tmpLenValue",ctx=1, varType=Int)
31 | i.increment()
32 |
33 | i.setTo(l)
34 |
35 | #ret.append(i.copy())
36 | ret.append(i)
37 |
38 | return ret
39 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/ord.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ...pyObjectManager.Real import Real
3 | from ...pyObjectManager.BitVec import BitVec
4 | from ...pyObjectManager.String import String
5 | from ...pyObjectManager.List import List
6 | from ...pyObjectManager.Char import Char
7 | import logging
8 | from ... import pyState
9 |
10 | logger = logging.getLogger("pyState:functions:ord")
11 |
12 | import z3
13 |
14 | def handle(state,call,obj,ctx=None):
15 | """
16 | Simulate ord funcion
17 | """
18 | ctx = ctx if ctx is not None else state.ctx
19 |
20 | # Resolve the object
21 | objs = state.resolveObject(obj,ctx=ctx)
22 |
23 | # Normalize
24 | objs = [objs] if type(objs) is not list else objs
25 |
26 | # Resolve calls if we need to
27 | retObjs = [x for x in objs if type(x) is pyState.ReturnObject]
28 | if len(retObjs) > 0:
29 | return retObjs
30 |
31 | # Loop through our input
32 | retList = []
33 | for obj in objs:
34 |
35 | # This is probably a script problem, not us
36 | if (type(obj) not in [String, Char]) or (type(obj) is String and len(obj) != 1):
37 | err = "handle: Invalid param for ord type {0}".format(type(obj))
38 | logger.error(err)
39 | raise Exception(err)
40 |
41 | # Grab a new var to work with
42 | ret = state.getVar("tmpOrdVal",ctx=1,varType=Int)
43 | ret.increment()
44 |
45 | # Sanitize String to Char
46 | if type(obj) is String:
47 | obj = obj[0]
48 |
49 | # Simple case, it's static
50 | if obj.isStatic():
51 | ret.setTo(ord(obj.getValue()))
52 |
53 | # If it's symbolic, we need help from z3
54 | else:
55 | # Tell z3 to convert the BitVec to an int, then set equal
56 | #ret.state.addConstraint(z3.BV2Int(obj.getZ3Object()) == ret.getZ3Object())
57 | ret.setTo(obj)
58 |
59 | retList.append(ret.copy())
60 |
61 | return retList
62 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/print.py:
--------------------------------------------------------------------------------
1 | from ... import pyState
2 |
3 | def handle(state,call,s,ctx=None):
4 | """
5 | Pretend to print stuff
6 | """
7 | ctx = ctx if ctx is not None else state.ctx
8 |
9 | s = state.resolveObject(s,ctx=ctx)
10 |
11 | # Resolve calls if we need to
12 | retObjs = [x for x in s if type(x) is pyState.ReturnObject]
13 | if len(retObjs) > 0:
14 | return retObjs
15 |
16 | for obj in s:
17 | print(obj)
18 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/pyState/BVS.py:
--------------------------------------------------------------------------------
1 | import z3
2 | import ast
3 | from ...z3Helpers import Z3_DEFAULT_BITVEC_SIZE
4 | from ....pyObjectManager.BitVec import BitVec
5 |
6 | def handle(state,call,size=ast.Num(Z3_DEFAULT_BITVEC_SIZE),ctx=None):
7 | """
8 | Returns a BitVec object. Use this to inform pySym that something should be BitVec symbolic
9 | """
10 | ctx = ctx if ctx is not None else state.ctx
11 |
12 | assert type(size) is ast.Num, "Unknown size for BVS of type {}".format(type(size))
13 |
14 | bvs = state.resolveObject(ast.Name('temp',0),ctx=1,varType=BitVec,kwargs={'size': size.n})
15 | assert len(bvs) == 1
16 |
17 | bvs = bvs[0]
18 | bvs.increment()
19 |
20 | return [bvs.copy()]
21 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/pyState/BVV.py:
--------------------------------------------------------------------------------
1 | import logging
2 | logger = logging.getLogger("pyState:functions:pyState:BVV")
3 |
4 | import z3
5 | import ast
6 | from ...z3Helpers import Z3_DEFAULT_BITVEC_SIZE
7 | from ....pyObjectManager.BitVec import BitVec
8 | from ....pyObjectManager.Int import Int
9 | from .... import pyState
10 |
11 | def _handle_num(i, size, ctx):
12 | """i is already resolved as Int or BitVec. size is not."""
13 |
14 | state = i.state.copy()
15 |
16 | # Resolve the size object
17 | size_vals = state.resolveObject(size,ctx=ctx)
18 |
19 | # Resolve calls if we need to
20 | retObjs = [x for x in size_vals if type(x) is pyState.ReturnObject]
21 | if len(retObjs) > 0:
22 | return retObjs
23 |
24 | ret = []
25 |
26 | # Loop through sizes
27 | for size in size_vals:
28 |
29 | state = size.state.copy()
30 |
31 | if type(size) not in [Int, BitVec]:
32 | error = "Unhandled size type of {}".format(type(size))
33 | logger.error(error)
34 | raise Exception(error)
35 |
36 | assert size.isStatic(), "Not handling symbolic size value for pyState.BVV right now."
37 |
38 | # Resolve it to be an int
39 | size = size.getValue()
40 |
41 | # Generate a BitVec object for this.
42 | bvv = state.resolveObject(ast.Name('tempBVV',0),ctx=1,varType=BitVec,kwargs={'size': size})
43 |
44 | assert len(bvv) == 1, "pyState.BVV somehow resolved two values for ast.Num??"
45 | bvv = bvv.pop()
46 |
47 | bvv.increment()
48 | bvv.setTo(i)
49 | ret.append(bvv.copy())
50 |
51 | return ret
52 |
53 | def handle(state,call,i,size=ast.Num(Z3_DEFAULT_BITVEC_SIZE),ctx=None):
54 | """
55 | Returns a BitVecVal object. This is helpful if we want to manually state what type a variable should be.
56 | """
57 | ctx = ctx if ctx is not None else state.ctx
58 |
59 | ret_bvv = []
60 |
61 | # Resolve the i object
62 | i_vals = state.resolveObject(i,ctx=ctx)
63 |
64 | # Resolve calls if we need to
65 | retObjs = [x for x in i_vals if type(x) is pyState.ReturnObject]
66 | if len(retObjs) > 0:
67 | return retObjs
68 |
69 | # Loop through our possible i values
70 | for i in i_vals:
71 |
72 | if type(i) in [Int, BitVec]:
73 | ret_bvv += _handle_num(i, size, ctx)
74 |
75 | else:
76 | error = "Unhandled i type of {}".format(type(i))
77 | logger.error(i)
78 | raise Exception(i)
79 |
80 | # Resolve calls if we need to
81 | retObjs = [x for x in ret_bvv if type(x) is pyState.ReturnObject]
82 | if len(retObjs) > 0:
83 | return retObjs
84 |
85 | return ret_bvv
86 |
87 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/pyState/Int.py:
--------------------------------------------------------------------------------
1 |
2 | import z3
3 | import ast
4 | from ....pyObjectManager.Int import Int
5 |
6 | def handle(state,call,ctx=None):
7 | """
8 | Returns an Int object. Use this to inform pySym that something should be Int symbolic
9 | """
10 | ctx = ctx if ctx is not None else state.ctx
11 |
12 | myInt = state.resolveObject(ast.Name('temp',0),ctx=1,varType=Int)
13 |
14 | # Everything is moved around as lists...
15 | for i in myInt:
16 | i.increment()
17 |
18 | return myInt.copy()
19 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/pyState/Real.py:
--------------------------------------------------------------------------------
1 | import z3
2 | import ast
3 | from ....pyObjectManager.Real import Real
4 | from ... import z3Helpers
5 |
6 | def handle(state,call,value=None,ctx=None):
7 | """
8 | Returns a z3 Real object. Use this to inform pySym that something should be Real symbolic
9 | (optional) value == the value to set this variable to
10 | """
11 | ctx = ctx if ctx is not None else state.ctx
12 |
13 | myReal = state.resolveObject(ast.Name('tempReal',0),ctx=ctx,varType=Real)
14 |
15 | ret = []
16 |
17 | for r in myReal:
18 |
19 | if value is not None:
20 | state = r.state
21 | value = state.resolveObject(value,ctx=ctx)
22 |
23 | for v in value:
24 | realObj,valueObj = z3Helpers.z3_matchLeftAndRight(r,v,ast.Add)
25 | #r.setTo(v)
26 | r.increment()
27 | state.addConstraint(r.getZ3Object() == valueObj)
28 | ret.append(r.copy())
29 |
30 | else:
31 | r.increment()
32 | ret.append(r.copy())
33 |
34 | return ret
35 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/pyState/String.py:
--------------------------------------------------------------------------------
1 |
2 | import z3
3 | import ast
4 | from ...z3Helpers import Z3_MAX_STRING_LENGTH
5 | from ....pyObjectManager.String import String
6 |
7 | def handle(state,call,length=ast.Num(Z3_MAX_STRING_LENGTH),ctx=None):
8 | """
9 | Returns a String object. This is helpful if we want to manually state what type a variable should be.
10 | Create a completely symbolic array of default max length:
11 | x = pyState.String()
12 | """
13 | ctx = ctx if ctx is not None else state.ctx
14 |
15 | assert type(length) in [ast.Num,int]
16 | length = length.n if type(length) is ast.Num else length
17 |
18 | string = state.getVar('pyStateStringTemp',ctx=1,varType=String,kwargs={'length': length})
19 | string.increment()
20 |
21 | return [string.copy()]
22 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/random/randint.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from ....pyObjectManager.Int import Int
3 | from ....pyObjectManager import CTX_RETURNS
4 | from .... import pyState
5 | import z3
6 |
7 | logger = logging.getLogger("pyState:functions:random.randint")
8 |
9 |
10 | def handle(state,call,a,b,ctx=None):
11 | """
12 | Implements python random.randint
13 | """
14 | ctx = ctx if ctx is not None else state.ctx
15 |
16 | # Resolve arguments
17 | a_list = state.resolveObject(a,ctx=ctx)
18 |
19 | # If we're waiting on a symbolic call, return
20 | retObjs = [x for x in a_list if type(x) is pyState.ReturnObject]
21 | if len(retObjs) > 0:
22 | return retObjs
23 |
24 | b_list = state.resolveObject(b,ctx=ctx)
25 |
26 | # If we're waiting on a symbolic call, return
27 | retObjs = [x for x in b_list if type(x) is pyState.ReturnObject]
28 | if len(retObjs) > 0:
29 | return retObjs
30 |
31 | ret = []
32 |
33 | # Generally this will only be a single a and b value, but you never know.
34 | for a in a_list:
35 |
36 | # Not handling symbolic a rn
37 | if not a.isStatic():
38 | exc = "Not handling symbolic 'a' value in random.randint right now."
39 | logger.error(exc)
40 | raise Exception(exc)
41 |
42 | for b in b_list:
43 |
44 | # Not handling symbolic b rn
45 | if not b.isStatic():
46 | exc = "Not handling symbolic 'b' value in random.randint right now."
47 | logger.error(exc)
48 | raise Exception(exc)
49 |
50 | s = state.copy()
51 |
52 | # Create a new Int
53 | obj = s.getVar('tmpRandomRandint',ctx=CTX_RETURNS,varType=Int)
54 |
55 | # Add constraints
56 | s.addConstraint(z3.And(obj.getZ3Object() >= int(a), obj.getZ3Object() <= int(b)))
57 |
58 | # Done with this command
59 | #print(s.path.pop(0))
60 |
61 | ret.append(obj)
62 |
63 | return ret
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/range.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.List import List
2 | from ...pyObjectManager.Int import Int
3 | from ...pyObjectManager.BitVec import BitVec
4 | import itertools
5 | from ... import pyState
6 | import logging
7 |
8 | logger = logging.getLogger("pyState:functions:range")
9 |
10 | def handle(state,call,a,b=None,c=None,ctx=None):
11 | """
12 | Simulate range funcion
13 | """
14 | ctx = ctx if ctx is not None else state.ctx
15 |
16 | # Resolve the vars
17 | aa = state.resolveObject(a,ctx=ctx)
18 |
19 | # Normalize
20 | aa = [aa] if type(aa) is not list else aa
21 |
22 | # Resolve calls if we need to
23 | retObjs = [x for x in aa if type(x) is pyState.ReturnObject]
24 | if len(retObjs) > 0:
25 | return retObjs
26 |
27 | bb = state.resolveObject(b,ctx=ctx) if b is not None else None
28 |
29 | # Normalize
30 | bb = [bb] if type(bb) is not list else bb
31 |
32 | # Resolve calls if we need to
33 | retObjs = [x for x in bb if type(x) is pyState.ReturnObject]
34 | if len(retObjs) > 0:
35 | return retObjs
36 |
37 | cc = state.resolveObject(c,ctx=ctx) if c is not None else None
38 |
39 | # Normalize
40 | cc = [cc] if type(cc) is not list else cc
41 |
42 | # Resolve calls if we need to
43 | retObjs = [x for x in cc if type(x) is pyState.ReturnObject]
44 | if len(retObjs) > 0:
45 | return retObjs
46 |
47 | ret = []
48 |
49 | # Loop through all possibilities
50 | for a,b,c in itertools.product(aa,bb,cc):
51 |
52 | ##############
53 | # a Concrete #
54 | ##############
55 |
56 | if type(a) not in [int,type(None)]:
57 | if a.isStatic():
58 | a = a.getValue()
59 |
60 | # Check if it's a variable that only has one possibility
61 | elif type(a) in [Int, BitVec] and len(state.any_n_int(a,2)) == 1:
62 | a = state.any_int(a)
63 |
64 | else:
65 | err = "handle: Don't know how to handle symbolic integers at the moment"
66 | logger.error(err)
67 | raise Exception(err)
68 |
69 |
70 | ##############
71 | # b Concrete #
72 | ##############
73 | if type(b) not in [int,type(None)]:
74 | if b.isStatic():
75 | b = b.getValue()
76 |
77 | # Check if it's a variable that only has one possibility
78 | elif type(b) in [Int, BitVec] and len(state.any_n_int(b,2)) == 1:
79 | b = state.any_int(b)
80 |
81 | else:
82 | err = "handle: Don't know how to handle symbolic integers at the moment"
83 | logger.error(err)
84 | raise Exception(err)
85 |
86 |
87 | ##############
88 | # c Concrete #
89 | ##############
90 |
91 | if type(c) not in [int,type(None)]:
92 | if c.isStatic():
93 | c = c.getValue()
94 |
95 | # Check if it's a variable that only has one possibility
96 | elif type(c) in [Int, BitVec] and len(state.any_n_int(c,2)) == 1:
97 | lower = state.any_int(c)
98 |
99 | else:
100 | err = "handle: Don't know how to handle symbolic integers at the moment"
101 | logger.error(err)
102 | raise Exception(err)
103 |
104 |
105 | # Create the return List object
106 | out = state.getVar("range",ctx=1,varType=List)
107 | out.increment()
108 |
109 | if b == None:
110 | rangeOut = range(a)
111 |
112 | elif c == None:
113 | rangeOut = range(a,b)
114 |
115 | else:
116 | rangeOut = range(a,b,c)
117 |
118 | # Copy the output
119 | for var in rangeOut:
120 | out.append(Int,kwargs={'value':var})
121 |
122 | # Return a copy
123 | ret.append(out.copy())
124 |
125 | return ret
126 |
127 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/str.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ...pyObjectManager.Real import Real
3 | from ...pyObjectManager.BitVec import BitVec
4 | from ...pyObjectManager.String import String
5 | from ...pyObjectManager.List import List
6 | import logging
7 | from ... import pyState
8 |
9 | logger = logging.getLogger("pyState:functions:str")
10 |
11 |
12 | def handle(state,call,obj,ctx=None):
13 | """
14 | Simulate str funcion
15 | """
16 | ctx = ctx if ctx is not None else state.ctx
17 |
18 | # Resolve the object
19 | objs = state.resolveObject(obj,ctx=ctx)
20 |
21 | # Normalize
22 | objs = [objs] if type(objs) is not list else objs
23 |
24 | # Resolve calls if we need to
25 | retObjs = [x for x in objs if type(x) is pyState.ReturnObject]
26 | if len(retObjs) > 0:
27 | return retObjs
28 |
29 | # Loop through objects
30 | retList = []
31 | for obj in objs:
32 |
33 | if type(obj) not in [Int, Real, BitVec, List]:
34 | # Only know how to do str on numbers for now
35 | err = "handle: Don't know how to handle type {0}".format(type(obj))
36 | logger.error(err)
37 | raise Exception(err)
38 |
39 | # Only dealing with concrete values for now.
40 | if obj.isStatic():
41 | ret = state.getVar("tmpStrVal",ctx=1,varType=String)
42 | ret.increment()
43 | # Utilize pyObjectManager class methods
44 | ret.setTo(obj.__str__(),clear=True)
45 |
46 | # TODO: Deal with symbolic values (returning list of possibilities)
47 | else:
48 | err = "handle: Don't know how to handle symbolic ints for now"
49 | logger.error(err)
50 | raise Exception(err)
51 |
52 |
53 | retList.append(ret.copy())
54 |
55 | return retList
56 |
--------------------------------------------------------------------------------
/pySym/pyState/functions/zip.py:
--------------------------------------------------------------------------------
1 | from ...pyObjectManager.Int import Int
2 | from ...pyObjectManager.Real import Real
3 | from ...pyObjectManager.BitVec import BitVec
4 | from ...pyObjectManager.String import String
5 | from ...pyObjectManager.List import List
6 | import logging
7 | from ... import pyState
8 | import itertools
9 |
10 | logger = logging.getLogger("pyState:functions:zip")
11 |
12 |
13 | def handle(state,call,left,right,ctx=None):
14 | """
15 | Simulate zip funcion
16 | """
17 | ctx = ctx if ctx is not None else state.ctx
18 |
19 | # Resolve the object
20 | lefts = state.resolveObject(left,ctx=ctx)
21 |
22 | # Normalize
23 | lefts = [lefts] if type(lefts) is not list else lefts
24 |
25 | # Resolve calls if we need to
26 | retObjs = [x for x in lefts if type(x) is pyState.ReturnObject]
27 | if len(retObjs) > 0:
28 | return retObjs
29 |
30 | # Don't want to lose track of our vars
31 | lefts = [left.copy() for left in lefts]
32 |
33 | rights = state.resolveObject(right,ctx=ctx)
34 |
35 | # Normalize
36 | rights = [rights] if type(rights) is not list else rights
37 |
38 | # Resolve calls if we need to
39 | retObjs = [x for x in rights if type(x) is pyState.ReturnObject]
40 | if len(retObjs) > 0:
41 | return retObjs
42 |
43 | rights = [right.copy() for right in rights]
44 |
45 | ret = []
46 |
47 | # Loop through possibilities
48 | for left,right in itertools.product(lefts,rights):
49 |
50 | # Only handling List and String objects for now
51 | if type(left) not in [List, String]:
52 | err = "handle: Don't know how to handle type {0}".format(type(left))
53 | logger.error(err)
54 | raise Exception(err)
55 |
56 | if type(right) not in [List, String]:
57 | err = "handle: Don't know how to handle type {0}".format(type(right))
58 | logger.error(err)
59 | raise Exception(err)
60 |
61 | # Create our output List
62 | newList = state.getVar('tmpZipList',ctx=1,varType=List)
63 | newList.increment()
64 |
65 | # Might as well use Python's own zip function to help us
66 | for (l,r) in zip(left,right):
67 | # TODO: This should really be a Tuple, but I haven't implemented that yet.
68 | tempList = state.getVar('tmpZipInner',ctx=1,varType=List)
69 | tempList.increment()
70 | tempList.variables = [l,r]
71 | newList.variables.append(tempList.copy())
72 |
73 | ret.append(newList.copy())
74 |
75 | return ret
76 |
--------------------------------------------------------------------------------
/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | py.test --forked -d -n auto --cov=. --cov-config=.coveragerc tests/
3 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [aliases]
2 | test=pytest
3 |
4 | [tool:pytest]
5 | addopts = --forked -d -n auto --cov=pySym --cov-branch --cov-config=.coveragerc --cov-report=term --cov-report html tests/
6 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | """A setuptools based setup module.
2 |
3 | See:
4 | https://packaging.python.org/en/latest/distributing.html
5 | https://github.com/pypa/sampleproject
6 | """
7 |
8 | # Always prefer setuptools over distutils
9 | from setuptools import setup, find_packages
10 | # To use a consistent encoding
11 | from codecs import open
12 | from os import path
13 | import os
14 |
15 | here = path.abspath(path.dirname(__file__))
16 |
17 | #with open(path.join(here, 'README.md'), encoding='utf-8') as f:
18 | # long_description = f.read()
19 | long_description = "See website for more info."
20 |
21 | dev_tools = ['pytest','python-coveralls','coverage','pytest-cov','pytest-xdist','ipython', 'gprof2dot', 'sphinx', 'sphinx_rtd_theme']
22 |
23 | #
24 | # Install z3 or no?
25 | #
26 |
27 | install_requires=['prettytable','enforce']
28 |
29 | # Defaulting RTD builds to use pip z3 solver
30 | if "PYSYM_NO_Z3" not in os.environ or os.environ.get('READTHEDOCS', None) == 'True':
31 | install_requires.append('z3-solver')
32 |
33 | setup(
34 | name='pySym',
35 | version='0.0.2',
36 | description='Symbolic execution of python source.',
37 | long_description=long_description,
38 | # The project's main homepage.
39 | url='https://github.com/bannsec/pySym',
40 | author='Michael Bann',
41 | author_email='self@bannsecurity.com',
42 | license='MIT',
43 | classifiers=[
44 | # Pick your license as you wish (should match "license" above)
45 | 'License :: OSI Approved :: MIT License',
46 | 'Programming Language :: Python :: 3',
47 | 'Operating System :: POSIX :: Linux',
48 | 'Environment :: Console'
49 | ],
50 | keywords='symbolic execution python',
51 | packages=find_packages(exclude=['contrib', 'docs', 'tests', 'longer_tests']),
52 | install_requires=install_requires,
53 | setup_requires=['pytest-runner'],
54 | tests_require=dev_tools,
55 | extras_require={
56 | 'dev': dev_tools,
57 | },
58 |
59 | #entry_points={
60 | # 'console_scripts': [
61 | # 'pySym = pySym.pySym:main',
62 | # ],
63 | #},
64 |
65 | )
66 |
67 |
--------------------------------------------------------------------------------
/setup_detectOS.sh:
--------------------------------------------------------------------------------
1 | lowercase(){
2 | echo "$1" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/"
3 | }
4 |
5 | OS=`lowercase \`uname\``
6 | KERNEL=`uname -r`
7 | MACH=`uname -m`
8 |
9 | if [ "{$OS}" == "windowsnt" ]; then
10 | OS=windows
11 | elif [ "{$OS}" == "darwin" ]; then
12 | OS=mac
13 | else
14 | OS=`uname`
15 | if [ "${OS}" = "SunOS" ] ; then
16 | OS=Solaris
17 | ARCH=`uname -p`
18 | OSSTR="${OS} ${REV}(${ARCH} `uname -v`)"
19 | elif [ "${OS}" = "AIX" ] ; then
20 | OSSTR="${OS} `oslevel` (`oslevel -r`)"
21 | elif [ "${OS}" = "Linux" ] ; then
22 | if [ -f /etc/redhat-release ] ; then
23 | DistroBasedOn='RedHat'
24 | DIST=`cat /etc/redhat-release |sed s/\ release.*//`
25 | PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//`
26 | REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
27 | elif [ -f /etc/SuSE-release ] ; then
28 | DistroBasedOn='SuSe'
29 | PSUEDONAME=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//`
30 | REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //`
31 | elif [ -f /etc/mandrake-release ] ; then
32 | DistroBasedOn='Mandrake'
33 | PSUEDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//`
34 | REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//`
35 | elif [ -f /etc/debian_version ] ; then
36 | DistroBasedOn='Debian'
37 | DIST=`cat /etc/lsb-release | grep '^DISTRIB_ID' | awk -F= '{ print $2 }'`
38 | PSUEDONAME=`cat /etc/lsb-release | grep '^DISTRIB_CODENAME' | awk -F= '{ print $2 }'`
39 | REV=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F= '{ print $2 }'`
40 | fi
41 | if [ -f /etc/UnitedLinux-release ] ; then
42 | DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]"
43 | fi
44 | OS=`lowercase $OS`
45 | DistroBasedOn=`lowercase $DistroBasedOn`
46 | readonly OS
47 | readonly DIST
48 | readonly DistroBasedOn
49 | readonly PSUEDONAME
50 | readonly REV
51 | readonly KERNEL
52 | readonly MACH
53 | fi
54 |
55 | fi
56 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # because
2 |
--------------------------------------------------------------------------------
/tests/functions/List/test_function_List_insert.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | from pySym.pyObjectManager.Real import Real
15 | from pySym.pyObjectManager.List import List
16 | from pySym.pyObjectManager.String import String
17 | from pySym.pyObjectManager.Int import Int
18 | from pySym.pyObjectManager.Char import Char
19 | from pySym.pyObjectManager.BitVec import BitVec
20 |
21 | import pytest
22 |
23 | test1 = """
24 | s = pyState.String(6)
25 | c = pyState.String(1)[0]
26 | r = pyState.Real()
27 | bv = pyState.BVS(32)
28 | l = [1,2,3]
29 | l.insert(0, 0)
30 | l.insert(0, 1.234)
31 | l.insert(0,[1,2,4,5])
32 | l.insert(0,"test")
33 | l.insert(0,bv)
34 | l.insert(0,s)
35 | l.insert(0,c)
36 | l.insert(0,r)
37 |
38 | assert bv == 14
39 | assert r == 5.15
40 | assert c == "c"
41 | assert ord(s[0]) == ord('s')
42 | """
43 |
44 |
45 | def test_function_List_insert():
46 | b = ast_parse.parse(test1).body
47 | p = Path(b,source=test1)
48 | pg = PathGroup(p)
49 |
50 | pg.explore()
51 |
52 | # [5.15, 'c', 's\x00\x00\x00\x00\x00', 14, 'test', [1, 2, 4, 5], 1.234, 0, 1, 2, 3]
53 | assert len(pg.completed) == 1
54 |
55 | s = pg.completed[0].state.copy()
56 |
57 | l = s.getVar('l')
58 |
59 | assert type(l[0]) == Real
60 | assert type(l[1]) == String and len(l[1]) == 1
61 | assert type(l[2]) == String
62 | assert type(l[3]) == BitVec
63 | my_list = s.any_list(l)
64 | assert my_list[0] == 5.15
65 | assert my_list[1] == "c"
66 | assert my_list[2].startswith("s")
67 | assert my_list[3] == 14
68 | assert my_list[4] == "test"
69 | assert my_list[5] == [1,2,4,5]
70 | assert my_list[6] == 1.234
71 | assert my_list[7:] == [0,1,2,3]
72 |
73 |
--------------------------------------------------------------------------------
/tests/functions/random/test_randint.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 |
4 | import logging
5 | from pySym import Colorer
6 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
7 |
8 | from pySym import ast_parse
9 | import z3
10 | from pySym.pyPath import Path
11 | from pySym.pyPathGroup import PathGroup
12 | import pytest
13 |
14 | test1 = """
15 | r = random.randint(1337,31337)
16 | """
17 |
18 | test2 = """
19 | s = pyState.String(8)
20 | r = random.randint(0, s.index('a'))
21 | """
22 |
23 | def test_function_random_randint_statesplit():
24 | b = ast_parse.parse(test2).body
25 | p = Path(b,source=test2)
26 | pg = PathGroup(p)
27 |
28 | pg.explore()
29 | assert len(pg.completed) == 8
30 |
31 | # Check where each state maxes out to ensure we're splitting right
32 | max_values = set()
33 |
34 | for path in pg.completed:
35 |
36 | r = path.state.getVar('r')
37 |
38 | for i in range(16):
39 | if not r.canBe(i):
40 | max_values.add(i-1)
41 | break
42 | else:
43 | assert False, "Random went way out of range..."
44 |
45 | assert max_values == set([0,1,2,3,4,5,6,7])
46 |
47 |
48 | def test_function_random_randint_basic():
49 | b = ast_parse.parse(test1).body
50 | p = Path(b,source=test1)
51 | pg = PathGroup(p)
52 |
53 | pg.explore()
54 | assert len(pg.completed) == 1
55 |
56 | s = pg.completed[0].state.copy()
57 | r = s.getVar('r')
58 |
59 | assert r.canBe(1337)
60 | assert r.canBe(31337)
61 | assert not r.canBe(31338)
62 | assert not r.canBe(1336)
63 |
64 |
--------------------------------------------------------------------------------
/tests/longer_tests/test_one.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test = """
20 | def to_bits(length, N):
21 | return [int(i) for i in bin(N)[2:].zfill(length)]
22 |
23 | def from_bits(N):
24 | return int("".join(str(i) for i in N), 2)
25 |
26 | CRC_POLY = to_bits(65, (2**64) + 0xeff67c77d13835f7) # 0b11110111111110110011111000111011111010001001110000011010111110111
27 |
28 | def crc(mesg):
29 | mesg += CONST
30 | shift = 0
31 | while shift < len(mesg) - 64:
32 | if mesg[shift]:
33 | for i in range(65):
34 | mesg[shift + i] ^= CRC_POLY[i]
35 | shift += 1
36 | return mesg[-64:]
37 |
38 | INNER = to_bits(8, 0x36) * 8 # 0b0011011000110110001101100011011000110110001101100011011000110110
39 |
40 | def xor(x, y):
41 | return [g ^ h for (g, h) in zip(x, y)]
42 |
43 | def hmac(h, key, mesg):
44 | return h(xor(key, OUTER) + h(xor(key, INNER) + mesg))
45 |
46 | PLAIN_1 = "zupe zecret"
47 | PLAIN_2 = "BKPCTF"
48 |
49 | def str_to_bits(s):
50 | return [b for i in s for b in to_bits(8, ord(i))]
51 |
52 | def bits_to_hex(b):
53 | return hex(from_bits(b)).rstrip("L")
54 |
55 | PLAIN_1_BITS = str_to_bits(PLAIN_1)
56 | """
57 |
58 | def test_longer_one():
59 | b = ast_parse.parse(test).body
60 | p = Path(b,source=test)
61 | pg = PathGroup(p)
62 |
63 | pg.explore()
64 |
65 | assert len(pg.completed) == 1
66 |
67 | assert pg.completed[0].state.any_list('CRC_POLY') == [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1]
68 |
69 | assert pg.completed[0].state.any_list('INNER') == [0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0]
70 |
71 | assert pg.completed[0].state.any_list('PLAIN_1_BITS') == [0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0]
72 |
73 |
--------------------------------------------------------------------------------
/tests/scripts/assert_script_1.py:
--------------------------------------------------------------------------------
1 | def test():
2 | return 12
3 |
4 | i = pyState.Int()
5 | assert i % test() == 4
6 |
--------------------------------------------------------------------------------
/tests/scripts/basic_function.py:
--------------------------------------------------------------------------------
1 | x = 0
2 | y = 0
3 |
4 | y += 12
5 |
6 | pass # Hook point
7 |
8 | if y > 0:
9 | x = 1
10 | else:
11 | x = 0
12 |
--------------------------------------------------------------------------------
/tests/scripts/ord_symbolic_chr.py:
--------------------------------------------------------------------------------
1 | s = pyState.String(5)
2 | c = ord(s[1])
3 |
--------------------------------------------------------------------------------
/tests/test_function_List.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | import pytest
15 |
16 | test1 = """
17 | l = []
18 | l.append(1)
19 | l.append(2.3)
20 | l.append([1,2.2,3])
21 | """
22 |
23 | test2 = """
24 | s = pyState.String(8)
25 | l = []
26 | l.append(s.index('a'))
27 | """
28 |
29 | def test_function_List_append_statesplit():
30 | b = ast_parse.parse(test2).body
31 | p = Path(b,source=test2)
32 | pg = PathGroup(p)
33 |
34 | pg.explore()
35 | assert len(pg.completed) == 8
36 | assert set([p.state.any_list('l').pop() for p in pg.completed]) == set(range(8))
37 |
38 |
39 | def test_function_List_append():
40 | b = ast_parse.parse(test1).body
41 | p = Path(b,source=test1)
42 | pg = PathGroup(p)
43 |
44 | pg.explore()
45 | assert len(pg.completed) == 1
46 | assert pg.completed[0].state.any_list('l') == [1, 2.3, [1, 2.2, 3]]
47 |
48 |
--------------------------------------------------------------------------------
/tests/test_function_List_clear.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | l = [1,2,3]
21 | l.clear()
22 | """
23 |
24 | test2 = """
25 | l = [1,2,3]
26 | l.clear()
27 | l.append(5)
28 | """
29 |
30 | def test_function_String_clear_append():
31 | b = ast_parse.parse(test2).body
32 | p = Path(b,source=test2)
33 | pg = PathGroup(p)
34 |
35 | pg.explore()
36 |
37 | assert len(pg.completed) == 1
38 |
39 | assert pg.completed[0].state.any_list('l') == [5]
40 |
41 |
42 | def test_function_String_clear_basic():
43 | b = ast_parse.parse(test1).body
44 | p = Path(b,source=test1)
45 | pg = PathGroup(p)
46 |
47 | pg.explore()
48 |
49 | assert len(pg.completed) == 1
50 |
51 | assert pg.completed[0].state.any_list('l') == []
52 |
53 |
54 |
--------------------------------------------------------------------------------
/tests/test_function_String_index.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | s = "Test"
21 | x = s.index("{0}")
22 | """
23 |
24 | test2 = """
25 | s = pyState.String(10)
26 | x = s.index('a')
27 | """
28 |
29 | test3 = """
30 | s = pyState.String(10)
31 | x = -1
32 | if s[3] == "a":
33 | x = s.index('a')
34 | """
35 |
36 |
37 |
38 | def test_function_String_Index_PartiallySymbolic():
39 | b = ast_parse.parse(test3).body
40 | p = Path(b,source=test3)
41 | pg = PathGroup(p)
42 |
43 | pg.explore()
44 |
45 | # Every index should be a possibility
46 | assert len(pg.completed) == 5
47 |
48 | indexes = []
49 | # Make sure we got all of them
50 | for path in pg.completed:
51 | indexes.append(path.state.any_int('x'))
52 |
53 | assert set(indexes) == set(range(4)).union({-1})
54 |
55 |
56 |
57 | def test_function_String_Index_Symbolic():
58 | b = ast_parse.parse(test2).body
59 | p = Path(b,source=test2)
60 | pg = PathGroup(p)
61 |
62 | pg.explore()
63 |
64 | # Every index should be a possibility
65 | assert len(pg.completed) == 10
66 |
67 | indexes = []
68 | # Make sure we got all of them
69 | for path in pg.completed:
70 | indexes.append(path.state.any_int('x'))
71 |
72 | assert set(indexes) == set(range(10))
73 |
74 |
75 | def test_function_String_Index():
76 | b = ast_parse.parse(test1.format("T")).body
77 | p = Path(b,source=test1.format("T"))
78 | pg = PathGroup(p)
79 |
80 | pg.explore()
81 | assert len(pg.completed) == 1
82 |
83 | assert pg.completed[0].state.any_int('x') == 0
84 |
85 | b = ast_parse.parse(test1.format("t")).body
86 | p = Path(b,source=test1.format("t"))
87 | pg = PathGroup(p)
88 |
89 | pg.explore()
90 | assert len(pg.completed) == 1
91 |
92 | assert pg.completed[0].state.any_int('x') == 3
93 |
94 | b = ast_parse.parse(test1.format("es")).body
95 | p = Path(b,source=test1.format("es"))
96 | pg = PathGroup(p)
97 |
98 | pg.explore()
99 | assert len(pg.completed) == 1
100 |
101 | assert pg.completed[0].state.any_int('x') == 1
102 |
103 | b = ast_parse.parse(test1.format("st")).body
104 | p = Path(b,source=test1.format("st"))
105 | pg = PathGroup(p)
106 |
107 | pg.explore()
108 | assert len(pg.completed) == 1
109 |
110 | assert pg.completed[0].state.any_int('x') == 2
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/tests/test_function_String_join.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = ''.join(["1","2","3"])
21 | y = ','.join(["4","5","6"])
22 | z = "".join([str(i) for i in [1,2,3]])
23 | """
24 |
25 | test2 = """
26 | s = pyState.String(8)
27 | x = "".join([str(x) for x in range(s.index('a'))])
28 | """
29 |
30 | def test_function_strJoin_statesplit():
31 | b = ast_parse.parse(test2).body
32 | p = Path(b,source=test2)
33 | pg = PathGroup(p)
34 |
35 | pg.explore()
36 | assert len(pg.completed) == 8
37 | out = [p.state.any_str('x') for p in pg.completed]
38 | out.sort()
39 | assert out == ['', '0', '01', '012', '0123', '01234', '012345', '0123456']
40 |
41 |
42 | def test_function_strJoin():
43 | b = ast_parse.parse(test1).body
44 | p = Path(b,source=test1)
45 | pg = PathGroup(p)
46 |
47 | pg.explore()
48 | assert len(pg.completed) == 1
49 |
50 | assert pg.completed[0].state.any_str('x') == ''.join(["1","2","3"])
51 | assert pg.completed[0].state.any_str('y') == ','.join(["4","5","6"])
52 | assert pg.completed[0].state.any_str('z') == "".join([str(i) for i in [1,2,3]])
53 |
--------------------------------------------------------------------------------
/tests/test_function_String_rstrip.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = "test ".rstrip()
21 | y = "test".rstrip()
22 | z = "test".rstrip("t")
23 | d = "test".rstrip("st")
24 | """
25 |
26 | test2 = """
27 | s = pyState.String(8)
28 | x = "test1".rstrip(str(s.index('a')))
29 | """
30 |
31 | test3 = """
32 | s = pyState.String(2)
33 | x = "testt"
34 | x = x.rstrip(s)
35 | """
36 |
37 | test4 = """
38 | s = pyState.String(8)
39 | x = s.rstrip("x")
40 | """
41 |
42 | test5 = """
43 | s = "mee"
44 | s2 = pyState.String(1)
45 | x = ''.join([x for x in s.rstrip(s2)])
46 | """
47 |
48 | test6 = """
49 | x = "test".rstrip(pyState.String(1) + "t")
50 | """
51 |
52 | def test_function_String_rstrip_partiallySymbolic():
53 | b = ast_parse.parse(test6).body
54 | p = Path(b,source=test6)
55 | pg = PathGroup(p)
56 |
57 | pg.explore()
58 | assert len(pg.completed) == 3
59 | o = [p.state.any_str('x') for p in pg.completed]
60 | o.sort()
61 | assert o == ['te', 'tes', 'tes']
62 |
63 |
64 | def test_function_String_rstrip_Char():
65 | b = ast_parse.parse(test5).body
66 | p = Path(b,source=test5)
67 | pg = PathGroup(p)
68 |
69 | pg.explore()
70 | assert len(pg.completed) == 2
71 | assert set([p.state.any_str('x') for p in pg.completed]) == {"m","mee"}
72 |
73 |
74 | def test_function_String_rstrip_symbolicStrip():
75 | b = ast_parse.parse(test3).body
76 | p = Path(b,source=test3)
77 | pg = PathGroup(p)
78 |
79 | pg.explore()
80 | assert len(pg.completed) == 5
81 | o = [p.state.any_str('x') for p in pg.completed]
82 | o.sort()
83 | # 3 cases. 1) both chars miss, 2) one char hit's "t" and the other misses. 3) one hits
84 | # "t" and the other hits "s"
85 | assert o == ['te', 'te', 'tes', 'tes', 'testt']
86 |
87 | b = ast_parse.parse(test4).body
88 | p = Path(b,source=test4)
89 | pg = PathGroup(p)
90 |
91 | pg.explore()
92 | assert len(pg.completed) == 9
93 |
94 | # TODO: This is a brittle match..
95 | o = [p.state.any_str('s') for p in pg.completed]
96 | # Sort by number of 'x' that appear in the output
97 | o = sorted(o, key=lambda x: x.count('x'))
98 | assert not o[0].endswith("x")
99 | for x in range(1,8):
100 | assert o[x].endswith("x"*x)
101 | #['\x00\x00\x00\x00\x00\x00\x00\x00', '\x00\x00\x00\x00\x00\x00\x00x', '\x00\x00\x00\x00\x00\x00xx', '\x00\x00\x00\x00\x00xxx', '\x00\x00\x00\x00xxxx', '\x00\x00\x00xxxxx', '\x00\x00xxxxxx', '\x00xxxxxxx', 'xxxxxxxx']
102 |
103 |
104 |
105 | def test_function_String_rstrip_statesplit():
106 | b = ast_parse.parse(test2).body
107 | p = Path(b,source=test2)
108 | pg = PathGroup(p)
109 |
110 | pg.explore()
111 | assert len(pg.completed) == 8
112 | o = [p.state.any_str('x') for p in pg.completed]
113 | o.sort()
114 | assert o == ['test', 'test1', 'test1', 'test1', 'test1', 'test1', 'test1', 'test1']
115 |
116 |
117 | def test_function_String_rstrip():
118 | b = ast_parse.parse(test1).body
119 | p = Path(b,source=test1)
120 | pg = PathGroup(p)
121 |
122 | pg.explore()
123 | assert len(pg.completed) == 1
124 |
125 | assert pg.completed[0].state.any_str('x') == "test ".rstrip()
126 | assert pg.completed[0].state.any_str('y') == "test".rstrip()
127 | assert pg.completed[0].state.any_str('z') == "test".rstrip("t")
128 | assert pg.completed[0].state.any_str('d') == "test".rstrip("st")
129 |
130 |
--------------------------------------------------------------------------------
/tests/test_function_String_zfill.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = "test"
21 | y = x.zfill(5)
22 | z = x.zfill(3)
23 | d = x.zfill(10)
24 | """
25 |
26 | test2 = """
27 | s = pyState.String(8)
28 | x = "test"
29 | y = x.zfill(s.index('a'))
30 | """
31 |
32 | def test_function_String_zfill_statesplit():
33 | b = ast_parse.parse(test2).body
34 | p = Path(b,source=test2)
35 | pg = PathGroup(p)
36 |
37 | pg.explore()
38 |
39 | # Every index should be a possibility
40 | assert len(pg.completed) == 8
41 |
42 | o = [p.state.any_str('y') for p in pg.completed]
43 | o.sort()
44 | assert o == ['000test', '00test', '0test', 'test', 'test', 'test', 'test', 'test']
45 |
46 |
47 | def test_function_String_zfill_static():
48 | b = ast_parse.parse(test1).body
49 | p = Path(b,source=test1)
50 | pg = PathGroup(p)
51 |
52 | pg.explore()
53 |
54 | # Every index should be a possibility
55 | assert len(pg.completed) == 1
56 |
57 | assert pg.completed[0].state.any_str('x') == "test"
58 | assert pg.completed[0].state.any_str('y') == "0test"
59 | assert pg.completed[0].state.any_str('z') == "test"
60 | assert pg.completed[0].state.any_str('d') == "000000test"
61 |
62 |
--------------------------------------------------------------------------------
/tests/test_function_abs.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | #myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = 10
21 | y = -10
22 | z = pyState.Int()
23 | a = abs(x)
24 | b = abs(y)
25 | c = abs(10)
26 | d = abs(-10)
27 | e = abs(z)
28 | """
29 |
30 | def test_funcion_abs():
31 | b = ast_parse.parse(test1).body
32 | p = Path(b,source=test1)
33 | pg = PathGroup(p)
34 |
35 | pg.explore()
36 |
37 | assert len(pg.completed) == 1
38 | assert pg.completed[0].state.any_int('a') == 10
39 | assert pg.completed[0].state.any_int('b') == 10
40 | assert pg.completed[0].state.any_int('c') == 10
41 | assert pg.completed[0].state.any_int('d') == 10
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/tests/test_function_bin.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | s = 5
21 | x = bin(12)
22 | y = bin(13)[2:]
23 | z = bin(s)
24 | """
25 |
26 | test2 = """
27 | s = pyState.String(8)
28 | x = bin(s.index('a'))
29 | """
30 |
31 | def test_funcion_bin_StateSplit():
32 | b = ast_parse.parse(test2).body
33 | p = Path(b,source=test2)
34 | pg = PathGroup(p)
35 |
36 | pg.explore()
37 |
38 | # We should get 8 states back
39 | assert len(pg.completed) == 8
40 | assert set([int(p.state.any_str('x'),2) for p in pg.completed]) == set(range(8))
41 |
42 |
43 | def test_function_bin():
44 | b = ast_parse.parse(test1).body
45 | p = Path(b,source=test1)
46 | pg = PathGroup(p)
47 |
48 | pg.explore()
49 | assert len(pg.completed) == 1
50 |
51 | assert pg.completed[0].state.any_str('x') == bin(12)
52 | assert pg.completed[0].state.any_str('y') == bin(13)[2:]
53 | assert pg.completed[0].state.any_str('z') == bin(5)
54 |
55 |
--------------------------------------------------------------------------------
/tests/test_function_chr.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 |
4 | import logging
5 | from pySym import Colorer
6 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
7 |
8 | from pySym import ast_parse
9 | import z3
10 | from pySym.pyPath import Path
11 | from pySym.pyPathGroup import PathGroup
12 | import pytest
13 | from pySym.pyObjectManager.Int import Int
14 | from pySym.pyObjectManager.Real import Real
15 | from pySym.pyObjectManager.BitVec import BitVec
16 | from pySym.pyObjectManager.List import List
17 | import pySym
18 |
19 | test1 = """
20 | i = 88 # 'X'
21 | c = chr(i)
22 | """
23 |
24 | test2 = """
25 | i = pyState.Int()
26 | c = chr(i)
27 | """
28 |
29 | def test_function_chr_symbolic_input():
30 | b = ast_parse.parse(test2).body
31 | p = Path(b,source=test2)
32 | pg = PathGroup(p)
33 | pg.explore()
34 |
35 | assert len(pg.completed) == 1
36 |
37 | i = pg.completed[0].state.getVar('i')
38 | c = pg.completed[0].state.getVar('c')
39 |
40 | # Set i, check that it propagates to c.
41 | i.setTo(ord('X'))
42 | assert str(c) == "X"
43 |
44 | def test_function_chr():
45 | b = ast_parse.parse(test1).body
46 | p = Path(b,source=test1)
47 | pg = PathGroup(p)
48 |
49 | pg.explore()
50 | assert len(pg.completed) == 1
51 |
52 | assert chr(pg.completed[0].state.any_int('c')) == 'X'
53 |
--------------------------------------------------------------------------------
/tests/test_function_hex.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = hex(12)
21 | y = 1337
22 | z = hex(y)
23 | """
24 |
25 | test2 = """
26 | s = pyState.String(8)
27 | x = hex(s.index('a'))
28 | """
29 |
30 | def test_function_hex_StateSplit():
31 | b = ast_parse.parse(test2).body
32 | p = Path(b,source=test2)
33 | pg = PathGroup(p)
34 |
35 | pg.explore()
36 | assert len(pg.completed) == 8
37 | assert set([int(p.state.any_str('x'),16) for p in pg.completed]) == set(range(8))
38 |
39 |
40 | def test_function_hex():
41 | b = ast_parse.parse(test1).body
42 | p = Path(b,source=test1)
43 | pg = PathGroup(p)
44 |
45 | pg.explore()
46 | assert len(pg.completed) == 1
47 |
48 | assert pg.completed[0].state.any_str('x') == hex(12)
49 | assert pg.completed[0].state.any_str('z') == hex(1337)
50 |
51 |
--------------------------------------------------------------------------------
/tests/test_function_int.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = int("123")
21 | y = int(12.3)
22 | z = int("0b1101",2)
23 | """
24 |
25 | test2 = """
26 | q = int("12","10")
27 | """
28 |
29 | test3 = """
30 | s = pyState.String(8)
31 | x = int(s.index('a'))
32 | """
33 |
34 | def test_function_int_statesplit():
35 | b = ast_parse.parse(test3).body
36 | p = Path(b,source=test3)
37 | pg = PathGroup(p)
38 |
39 | pg.explore()
40 | assert len(pg.completed) == 8
41 | assert set([p.state.any_int('x') for p in pg.completed]) == set(range(8))
42 |
43 |
44 | def test_function_int():
45 | b = ast_parse.parse(test1).body
46 | p = Path(b,source=test1)
47 | pg = PathGroup(p)
48 |
49 | pg.explore()
50 | assert len(pg.completed) == 1
51 |
52 | assert pg.completed[0].state.any_int('x') == int("123")
53 | assert pg.completed[0].state.any_int('y') == int(12.3)
54 | assert pg.completed[0].state.any_int('z') == int("0b1101",2)
55 |
56 | b = ast_parse.parse(test2).body
57 | p = Path(b,source=test2)
58 | pg = PathGroup(p)
59 |
60 | pg.explore()
61 | assert len(pg.errored) == 1
62 |
63 |
64 |
--------------------------------------------------------------------------------
/tests/test_function_len.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | s = "abcd"
21 | l = [x for x in s] + [1,2]
22 | x = len(s)
23 | y = len(l)
24 | """
25 |
26 | test2 = """
27 | s = pyState.String(8)
28 | x = len("A" * s.index('a'))
29 | """
30 |
31 | def test_fnuction_len_statesplit():
32 | b = ast_parse.parse(test2).body
33 | p = Path(b,source=test2)
34 | pg = PathGroup(p)
35 |
36 | pg.explore()
37 | assert len(pg.completed) == 8
38 | assert set([p.state.any_int('x') for p in pg.completed]) == set(range(8))
39 |
40 |
41 | def test_function_len():
42 | b = ast_parse.parse(test1).body
43 | p = Path(b,source=test1)
44 | pg = PathGroup(p)
45 |
46 | pg.explore()
47 | assert len(pg.completed) == 1
48 |
49 | assert pg.completed[0].state.any_int('x') == 4
50 | assert pg.completed[0].state.any_int('y') == 6
51 |
52 |
--------------------------------------------------------------------------------
/tests/test_function_ord.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 |
4 | import logging
5 | from pySym import Colorer
6 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
7 |
8 | from pySym import ast_parse
9 | import z3
10 | from pySym.pyPath import Path
11 | from pySym.pyPathGroup import PathGroup
12 | import pytest
13 | from pySym.pyObjectManager.Int import Int
14 | from pySym.pyObjectManager.Real import Real
15 | from pySym.pyObjectManager.BitVec import BitVec
16 | from pySym.pyObjectManager.List import List
17 | import pySym
18 |
19 | test1 = """
20 | x = ord("A")
21 | s = "Test"
22 | y = ord(s[0])
23 | """
24 |
25 | test2 = """
26 | s = pyState.String(8)
27 | x = ord(str(s.index('a')))
28 | """
29 |
30 | def test_function_ord_symbolic_input():
31 | proj = pySym.Project(os.path.join(myPath, "scripts", "ord_symbolic_chr.py"))
32 | pg = proj.factory.path_group()
33 | pg.explore()
34 |
35 | assert len(pg.completed) == 1
36 |
37 | s = pg.completed[0].state.getVar('s')
38 | c = pg.completed[0].state.getVar('c')
39 |
40 | # Set the integer value, back prop to the string
41 | c.setTo(ord('X'))
42 | assert str(s)[1] == "X"
43 |
44 |
45 | def test_function_ord_StateSplitting():
46 | b = ast_parse.parse(test2).body
47 | p = Path(b,source=test2)
48 | pg = PathGroup(p)
49 |
50 | pg.explore()
51 | assert len(pg.completed) == 8
52 | assert set([p.state.any_int('x') for p in pg.completed]) == set([ord(str(x)) for x in range(8)])
53 |
54 |
55 |
56 | def test_function_ord():
57 | b = ast_parse.parse(test1).body
58 | p = Path(b,source=test1)
59 | pg = PathGroup(p)
60 |
61 | pg.explore()
62 | assert len(pg.completed) == 1
63 |
64 | assert chr(pg.completed[0].state.any_int('x')) == "A"
65 | assert chr(pg.completed[0].state.any_int('y')) == "T"
66 |
67 |
68 |
--------------------------------------------------------------------------------
/tests/test_function_pyState_BVS.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 |
4 | import logging
5 | from pySym import Colorer
6 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
7 |
8 | from pySym import ast_parse
9 | import z3
10 | from pySym.pyPath import Path
11 | from pySym.pyPathGroup import PathGroup
12 | import pytest
13 | from pySym.pyObjectManager.Int import Int
14 | from pySym.pyObjectManager.Real import Real
15 | from pySym.pyObjectManager.BitVec import BitVec
16 | from pySym.pyObjectManager.List import List
17 | from pySym.pyState.z3Helpers import Z3_MAX_STRING_LENGTH
18 |
19 | test1 = """
20 | s1 = pyState.BVS(1)
21 | s2 = pyState.BVS(1)
22 | """
23 |
24 | test2 = """
25 | l = []
26 |
27 | for i in range(24):
28 | l.append(pyState.BVS(1))
29 | """
30 |
31 | def test_function_pyState_BVS_ret_as_list():
32 | b = ast_parse.parse(test2).body
33 | p = Path(b,source=test2)
34 | pg = PathGroup(p)
35 |
36 | pg.explore()
37 | assert len(pg.completed) == 1
38 |
39 | def test_function_pyState_BVS_basic():
40 | b = ast_parse.parse(test1).body
41 | p = Path(b,source=test1)
42 | pg = PathGroup(p)
43 |
44 | pg.explore()
45 | assert len(pg.completed) == 1
46 |
47 | s1 = pg.completed[0].state.getVar('s1')
48 | s2 = pg.completed[0].state.getVar('s2')
49 |
50 | # Make sure that we're not duplicating variables on creation
51 | assert str(s1.getZ3Object()) != str(s2.getZ3Object())
52 |
--------------------------------------------------------------------------------
/tests/test_function_pyState_BVV.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 |
4 | import logging
5 | from pySym import Colorer
6 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
7 |
8 | from pySym import ast_parse
9 | import z3
10 | from pySym.pyPath import Path
11 | from pySym.pyPathGroup import PathGroup
12 | import pytest
13 | from pySym.pyObjectManager.Int import Int
14 | from pySym.pyObjectManager.Real import Real
15 | from pySym.pyObjectManager.BitVec import BitVec
16 | from pySym.pyObjectManager.List import List
17 | from pySym.pyState.z3Helpers import Z3_MAX_STRING_LENGTH
18 |
19 | test1 = """
20 | x = pyState.BVV((16 >> 4)&1,1) # Results in BitVec 1 of size 1
21 | y = pyState.BVV((16 >> 4)&1,2**10) # Results in BitVec 1 of size 1024
22 | """
23 |
24 | def test_function_pyState_BVV_basic():
25 | b = ast_parse.parse(test1).body
26 | p = Path(b,source=test1)
27 | pg = PathGroup(p)
28 |
29 | pg.explore()
30 | assert len(pg.completed) == 1
31 |
32 | x = pg.completed[0].state.getVar('x')
33 | y = pg.completed[0].state.getVar('y')
34 |
35 | assert x.isStatic() and x.mustBe(1) and x.size == 1
36 | assert y.isStatic() and y.mustBe(1) and y.size == 1024
37 |
--------------------------------------------------------------------------------
/tests/test_function_pyState_Real.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 | from pySym.pyState.z3Helpers import Z3_MAX_STRING_LENGTH
19 |
20 | test1 = """
21 | s = pyState.Real()
22 | s2 = pyState.Real(123)
23 | s3 = pyState.Real(123.5)
24 | """
25 |
26 |
27 | def test_function_pyState_Real():
28 | b = ast_parse.parse(test1).body
29 | p = Path(b,source=test1)
30 | pg = PathGroup(p)
31 |
32 | pg.explore()
33 | assert len(pg.completed) == 1
34 |
35 | s = pg.completed[0].state.getVar('s')
36 | s2 = pg.completed[0].state.getVar('s2')
37 | s3 = pg.completed[0].state.getVar('s3')
38 |
39 | assert type(s) == Real
40 | assert type(s2) == Real
41 | assert type(s3) == Real
42 |
43 | assert s.canBe(123.0)
44 | assert s2.getValue() == 123.0
45 | assert s3.getValue() == 123.5
46 |
--------------------------------------------------------------------------------
/tests/test_function_pyState_String.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 | from pySym.pyState.z3Helpers import Z3_MAX_STRING_LENGTH
19 |
20 | test1 = """
21 | s = pyState.String(32)
22 | s2 = pyState.String()
23 | """
24 |
25 |
26 | def test_function_pyState_String():
27 | b = ast_parse.parse(test1).body
28 | p = Path(b,source=test1)
29 | pg = PathGroup(p)
30 |
31 | pg.explore()
32 | assert len(pg.completed) == 1
33 |
34 | s = pg.completed[0].state.getVar('s')
35 | s2 = pg.completed[0].state.getVar('s2')
36 |
37 | assert len(s) == 32
38 | assert len(s2) == Z3_MAX_STRING_LENGTH
39 |
40 |
--------------------------------------------------------------------------------
/tests/test_function_range.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | import pytest
15 |
16 | test1 = """
17 | out = 0
18 | for i in range(0,10,2):
19 | for j in range(5):
20 | out += i + j
21 | """
22 |
23 | test2 = """
24 | out = 0
25 | l = range(4,10)
26 | """
27 |
28 | test3 = """
29 | out = 0
30 | l = range(12)
31 | """
32 |
33 | test4 = """
34 | s = pyState.String(8)
35 | x = range(s.index('a'))
36 | """
37 |
38 | def test_function_range_StateSplit():
39 | b = ast_parse.parse(test4).body
40 | p = Path(b,source=test4)
41 | pg = PathGroup(p)
42 |
43 | pg.explore()
44 | assert len(pg.completed) == 8
45 | out = [p.state.any_list('x') for p in pg.completed]
46 | out.sort()
47 | assert out == [[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5, 6]]
48 |
49 |
50 | def test_function_range():
51 | b = ast_parse.parse(test1).body
52 | p = Path(b,source=test1)
53 | pg = PathGroup(p)
54 |
55 | pg.explore()
56 |
57 | assert len(pg.completed) == 1
58 | assert pg.completed[0].state.any_int('out') == 150
59 |
60 | b = ast_parse.parse(test2).body
61 | p = Path(b,source=test2)
62 | pg = PathGroup(p)
63 |
64 | pg.explore()
65 | assert len(pg.completed) == 1
66 | assert pg.completed[0].state.any_list('l') == [4, 5, 6, 7, 8, 9]
67 |
68 | b = ast_parse.parse(test3).body
69 | p = Path(b,source=test3)
70 | pg = PathGroup(p)
71 |
72 | pg.explore()
73 | assert len(pg.completed) == 1
74 | assert pg.completed[0].state.any_list('l') == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
75 |
76 |
--------------------------------------------------------------------------------
/tests/test_function_str.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | s = str(12)
21 | s2 = str(1.2)
22 | s3 = str([1,2,3])
23 | """
24 |
25 | test2 = """
26 | s = pyState.String(8)
27 | x = str(s.index('a'))
28 | """
29 |
30 | def test_function_str_statesplit():
31 | b = ast_parse.parse(test2).body
32 | p = Path(b,source=test2)
33 | pg = PathGroup(p)
34 |
35 | pg.explore()
36 | assert len(pg.completed) == 8
37 |
38 | set([int(p.state.any_str('x')) for p in pg.completed]) == set(range(8))
39 |
40 |
41 | def test_function_str():
42 | b = ast_parse.parse(test1).body
43 | p = Path(b,source=test1)
44 | pg = PathGroup(p)
45 |
46 | pg.explore()
47 | assert len(pg.completed) == 1
48 |
49 | assert pg.completed[0].state.any_str('s') == str(12)
50 | assert pg.completed[0].state.any_str('s2') == str(1.2)
51 | assert pg.completed[0].state.any_str('s3') == str([1,2,3])
52 |
--------------------------------------------------------------------------------
/tests/test_function_zip.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | l = zip([1,2,3],[4,5,6])
21 | l1 = [1,2,3]
22 | l2 = [4,5,6]
23 | l3 = zip(l1,l2)
24 | l4 = ["1","2","3"]
25 | l5 = ["4","5","6"]
26 | l6 = zip(l4,l5)
27 | l7 = zip(["1","2","3","4"],["5","6"])
28 | l8 = zip(["1","2"],["3","4","5","6"])
29 | l9 = zip([1,2,3],"abc")
30 | """
31 |
32 |
33 | def test_function_zip():
34 | b = ast_parse.parse(test1).body
35 | p = Path(b,source=test1)
36 | pg = PathGroup(p)
37 |
38 | pg.explore()
39 | assert len(pg.completed) == 1
40 |
41 | assert pg.completed[0].state.any_list('l') == [[1, 4], [2, 5], [3, 6]]
42 | assert pg.completed[0].state.any_list('l3') == [[1, 4], [2, 5], [3, 6]]
43 | assert pg.completed[0].state.any_list('l6') == [["1", "4"], ["2", "5"], ["3", "6"]]
44 | assert pg.completed[0].state.any_list('l7') == [["1","5"], ["2","6"]]
45 | assert pg.completed[0].state.any_list('l8') == [["1","3"], ["2","4"]]
46 | assert pg.completed[0].state.any_list('l9') == [[1,"a"],[2,"b"],[3,"c"]]
47 |
48 |
49 |
--------------------------------------------------------------------------------
/tests/test_path.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | from pySym import ast_parse
6 | import z3
7 | from pySym.pyPath import Path
8 | import pytest
9 |
10 | test1 = "x = 1\ny = 2"
11 |
12 | simpleIf = """
13 | x = 1
14 | y = 1
15 | if x > y:
16 | print("This shouldn't hit")
17 | else:
18 | print("This should hit")
19 | x = 2
20 | """
21 |
22 | testIfReturn = """
23 | x = 1
24 | y = 1.2
25 | if y > x:
26 | x += 1
27 | else:
28 | x -= 1
29 |
30 | y += 1
31 | """
32 |
33 | def test_ifReturn():
34 | b = ast_parse.parse(testIfReturn).body
35 | p = Path(b,source=testIfReturn)
36 | p = p.step()[0].step()[0]
37 | ifSide,elseSide = p.step()
38 | ifSide = ifSide.step()[0].step()[0]
39 | elseSide = elseSide.step()[0].step()[0]
40 |
41 | assert ifSide.state.any_int('x') == 2
42 | assert ifSide.state.any_real('y') == 2.2
43 | assert elseSide.state.any_int('x') == None
44 | assert elseSide.state.any_real('y') == None # Else side is wonky because it's not a possible path
45 |
46 |
47 | def test_basicPathStep():
48 | b = ast_parse.parse(test1).body
49 | p1 = Path(b,source=test1)
50 | p2 = p1.step()[0].step()[0]
51 | p1.printBacktrace()
52 | p2.printBacktrace()
53 | assert p2.state.any_int('x') == 1
54 | assert p2.state.any_int('y') == 2
55 | with pytest.raises(Exception):
56 | p1.state.any_int('x')
57 | with pytest.raises(Exception):
58 | p1.state.any_int('y')
59 |
60 | def test_pathCopy():
61 | b = ast_parse.parse(test1).body
62 | p = Path(b,source=test1)
63 | p2 = p.copy()
64 | assert p2 != p
65 | p = p.step()[0]
66 | assert p.state.any_int('x') == 1
67 | with pytest.raises(Exception):
68 | p2.state.any_int('x')
69 |
70 | def test_simpleIf():
71 | b = ast_parse.parse(simpleIf).body
72 | p = Path(b,source=simpleIf)
73 | # Step through the "if" statement
74 | p = p.step()[0]
75 | p = p.step()[0]
76 | p2 = p.step()
77 | ifSide = p2[0]
78 | elseSide = p2[1]
79 |
80 | # ifSide's path should now be inside, meaning only the print statement
81 | assert len(ifSide.state.path) == 1
82 | # Else should be in the else statement
83 | assert len(elseSide.state.path) == 2
84 |
85 | # Neither have anything to do after the if statement
86 | assert len(ifSide.state.callStack) == 1
87 | assert len(elseSide.state.callStack) == 0
88 |
89 | # If side should not be possible
90 | assert not ifSide.state.isSat()
91 | assert elseSide.state.isSat()
92 |
93 | # Track expected number of assertions
94 | #assert len(ifSide.state.solver.assertions()) == 3
95 | #assert len(elseSide.state.solver.assertions()) == 3
96 |
97 | # Make sure the answer makes sense
98 | assert ifSide.state.any_int('x') == None
99 | assert elseSide.state.any_int('x') == 1
100 |
--------------------------------------------------------------------------------
/tests/test_project.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 |
4 | import z3
5 | import pySym
6 | import pytest
7 |
8 | def test_basic_hooking():
9 | # Temporarily bastardizing the hook dictionary to pass state back to my test. ONLY for this test.
10 | proj = pySym.Project(os.path.join(myPath, "scripts", "basic_function.py"))
11 |
12 | def my_hook(state):
13 | state._project._hooks[6969] = True
14 | assert isinstance(state, pySym.pyState.State)
15 |
16 | proj.hook(6, my_hook)
17 | proj._hooks[6969] = False
18 | pg = proj.factory.path_group()
19 | pg.explore()
20 |
21 | assert proj._hooks[6969]
22 |
23 | def test_basic_project():
24 | proj = pySym.Project(os.path.join(myPath, "scripts", "basic_function.py"))
25 | pg = proj.factory.path_group()
26 | pg.explore()
27 |
28 | assert len(pg.deadended) == 1
29 | assert len(pg.completed) == 1
30 | assert pg.completed[0].state.any_int('x') == 1
31 |
32 | # Make sure we're passing the project through fully
33 | assert pg._project is proj
34 | assert pg.deadended[0]._project is proj
35 | assert pg.deadended[0].state._project is proj
36 | assert pg.completed[0]._project is proj
37 | assert pg.completed[0].state._project is proj
38 |
39 |
--------------------------------------------------------------------------------
/tests/test_pyObjectManager.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | l = [1,2.2,3]
21 | q = [1,2,[3,4]]
22 | """
23 |
24 | test2 = """
25 | l = [1,2,3]
26 | s = "test"
27 | i = 1337
28 | bvs = pyState.BVS(32)
29 | """
30 |
31 | def test_pyObjectManager_uuid():
32 | b = ast_parse.parse(test2).body
33 | p = Path(b,source=test2)
34 | pg = PathGroup(p)
35 |
36 | pg.explore()
37 | assert len(pg.completed) == 1
38 |
39 | s = pg.completed[0].state.copy()
40 | l = s.getVar('l')
41 | for elm in l:
42 | assert type(elm.uuid) is bytes
43 | assert type(l.uuid) is bytes
44 |
45 | st = s.getVar('s')
46 | assert type(st.uuid) is bytes
47 | for elm in st:
48 | assert type(elm.uuid) is bytes
49 |
50 | i = s.getVar('i')
51 | assert type(i.uuid) is bytes
52 |
53 | bvs = s.getVar('bvs')
54 | assert type(bvs.uuid) is bytes
55 |
56 |
57 | def test_pyObjectManager_getParent():
58 | b = ast_parse.parse(test1).body
59 | p = Path(b,source=test1)
60 | pg = PathGroup(p)
61 |
62 | pg.explore()
63 | assert len(pg.completed) == 1
64 |
65 | l = pg.completed[0].state.getVar('l')
66 | i = l[2]
67 |
68 | # Make sure it returned the right object
69 | assert pg.completed[0].state.objectManager.getParent(i) == l
70 |
71 | q = pg.completed[0].state.getVar('q')
72 | i = q[2][0]
73 |
74 | # Check that it recurses fully
75 | assert pg.completed[0].state.objectManager.getParent(i) == q[2]
76 |
77 |
78 |
--------------------------------------------------------------------------------
/tests/test_pyObjectManager_BitVec.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = pyState.BVV(5,16)
21 | """
22 |
23 | test2 = """
24 | x = pyState.BVS(32)
25 | y = pyState.BVV(15,32)
26 | """
27 |
28 | test3 = """
29 | x = pyState.BVV(1234,32)
30 | """
31 |
32 | test4 = """
33 | x = pyState.BVS(32)
34 | assert x == 1234
35 | """
36 |
37 | def test_pyObjectManager_BitVec_as_int():
38 | b = ast_parse.parse(test4).body
39 | p = Path(b,source=test4)
40 | pg = PathGroup(p)
41 |
42 | pg.explore()
43 | assert len(pg.completed) == 1
44 |
45 | s = pg.completed[0].state.copy()
46 | x = s.getVar('x')
47 | assert int(x) == 1234
48 |
49 |
50 | def test_pyObjectManager_BitVec_is_unconstrained():
51 | b = ast_parse.parse(test2).body
52 | p = Path(b,source=test2)
53 | pg = PathGroup(p)
54 |
55 | pg.explore()
56 | assert len(pg.completed) == 1
57 |
58 | s = pg.completed[0].state.copy()
59 | x = s.getVar('x')
60 |
61 | assert x.is_unconstrained
62 |
63 | # add a real constraint
64 | s.addConstraint(x.getZ3Object() > 14)
65 | assert x.is_constrained
66 |
67 |
68 | def test_pyObjectManager_BitVec_strPrint():
69 | b = ast_parse.parse(test3).body
70 | p = Path(b,source=test3)
71 | pg = PathGroup(p)
72 |
73 | pg.explore()
74 | assert len(pg.completed) == 1
75 |
76 | x = pg.completed[0].state.getVar('x')
77 | assert x.__str__() == "1234"
78 |
79 |
80 | def test_pyObjectManager_BitVec_setTo():
81 | b = ast_parse.parse(test2).body
82 | p = Path(b,source=test2)
83 | pg = PathGroup(p)
84 |
85 | pg.explore()
86 | assert len(pg.completed) == 1
87 |
88 | x = pg.completed[0].state.getVar('x')
89 | y = pg.completed[0].state.getVar('y')
90 |
91 | x.setTo(1337)
92 | assert pg.completed[0].state.any_int('x') == 1337
93 |
94 | x.increment()
95 | x.setTo(y)
96 | assert pg.completed[0].state.any_int('x') == 15
97 |
98 |
99 |
100 | def test_pyObjectManager_BitVec_isStatic():
101 | b = ast_parse.parse(test1).body
102 | p = Path(b,source=test1)
103 | pg = PathGroup(p)
104 |
105 | pg.explore()
106 | assert len(pg.completed) == 1
107 |
108 | x = pg.completed[0].state.getVar('x')
109 |
110 | assert x.isStatic()
111 | assert x.getValue() == 5
112 |
113 |
114 |
--------------------------------------------------------------------------------
/tests/test_pyObjectManager_Char.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 | from pySym.pyObjectManager.Char import Char
19 |
20 | test1 = """
21 | s = "Test"
22 | d = pyState.String(10)
23 | """
24 |
25 | test2 = """
26 | s = "Blerg"
27 | c2 = pyState.String(1)
28 | """
29 |
30 | test3 = """
31 | c = "b"
32 | """
33 |
34 | test4 = """
35 | s = pyState.String(1)
36 | d = "Test"
37 | e = "Feet"
38 | """
39 |
40 | def test_pyObjectManager_Char_is_unconstrained():
41 | b = ast_parse.parse(test2).body
42 | p = Path(b,source=test2)
43 | pg = PathGroup(p)
44 |
45 | pg.explore()
46 | assert len(pg.completed) == 1
47 |
48 | s = pg.completed[0].state.copy()
49 | c = s.getVar('s')[0]
50 |
51 | assert c.is_unconstrained
52 |
53 | # For now, this will add bounded int constraints to the solver...
54 | z3_obj = c.getZ3Object()
55 | # Those bounds should not count as constrained
56 | assert c.is_unconstrained
57 |
58 | # This constraint should eval to True, and not be added
59 | s.addConstraint(z3_obj > 5)
60 | assert c.is_unconstrained
61 |
62 | # Try with symbolic
63 | c = s.getVar('c2')[0]
64 |
65 | assert c.is_unconstrained
66 |
67 | # For now, this will add bounded int constraints to the solver...
68 | z3_obj = c.getZ3Object()
69 | # Those bounds should not count as constrained
70 | assert c.is_unconstrained
71 |
72 | # This should add a real constraint
73 | s.addConstraint(z3_obj > 5)
74 | assert c.is_constrained
75 |
76 | def test_pyObjectManager_Char_mustBe():
77 | b = ast_parse.parse(test4).body
78 | p = Path(b,source=test4)
79 | pg = PathGroup(p)
80 |
81 | pg.explore()
82 | assert len(pg.completed) == 1
83 |
84 | s = pg.completed[0].state.getVar('s')
85 | d = pg.completed[0].state.getVar('d')
86 | e = pg.completed[0].state.getVar('e')
87 |
88 | assert s[0].canBe(d[0])
89 | assert s[0].canBe("b")
90 | assert not s[0].mustBe("b")
91 | assert not s[0].mustBe(d[0])
92 | assert not s[0].canBe("test")
93 |
94 | assert d[1].canBe(e[1])
95 | assert d[1].mustBe(e[2])
96 |
97 |
98 | def test_pyObjectManager_Char_strPrint():
99 | b = ast_parse.parse(test3).body
100 | p = Path(b,source=test3)
101 | pg = PathGroup(p)
102 |
103 | pg.explore()
104 | assert len(pg.completed) == 1
105 |
106 | c = pg.completed[0].state.getVar('c')
107 | c = c[0]
108 |
109 | assert c.__str__() == "b"
110 |
111 |
112 | def test_pyObjectManager_Char_setTo():
113 | b = ast_parse.parse(test2).body
114 | p = Path(b,source=test2)
115 | pg = PathGroup(p)
116 |
117 | pg.explore()
118 | assert len(pg.completed) == 1
119 |
120 | c = pg.completed[0].state.getVar('c',varType=Char)
121 |
122 | c.setTo('x')
123 | assert c.getValue() == "x"
124 |
125 |
126 | def test_pyObjectManager_Char_isStatic():
127 | b = ast_parse.parse(test1).body
128 | p = Path(b,source=test1)
129 | pg = PathGroup(p)
130 |
131 | pg.explore()
132 | assert len(pg.completed) == 1
133 |
134 | s = pg.completed[0].state.getVar('s')
135 | d = pg.completed[0].state.getVar('d')
136 |
137 | assert s[0].isStatic()
138 | assert s[0].getValue() == "T"
139 |
140 | assert not d.isStatic()
141 |
142 |
--------------------------------------------------------------------------------
/tests/test_pyObjectManager_Int.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = 1
21 | """
22 |
23 | test2 = """
24 | x = pyState.Int()
25 | y = 5
26 | """
27 |
28 | test3 = """
29 | x = 12
30 | """
31 |
32 | test4 = """
33 | l = [pyState.Int(), pyState.Int()]
34 | if l[0] != l[1]:
35 | pass
36 | if l[0] == l[1]:
37 | pass
38 |
39 | pass
40 | """
41 |
42 | test5 = """
43 | i = pyState.Int()
44 | l = [0,1,2,3,4,5]
45 | x = l[i]
46 | """
47 |
48 | def test_pyObjectManager_Int_is_unconstrained():
49 | b = ast_parse.parse(test2).body
50 | p = Path(b,source=test2)
51 | pg = PathGroup(p)
52 |
53 | pg.explore()
54 | assert len(pg.completed) == 1
55 |
56 | s = pg.completed[0].state.copy()
57 | x = s.getVar('x')
58 |
59 | assert x.is_unconstrained
60 |
61 | # add a real constraint
62 | s.addConstraint(x.getZ3Object() > 5)
63 | assert x.is_constrained
64 |
65 |
66 | def test_pyObjectManager_Int_PostSet():
67 | b = ast_parse.parse(test5).body
68 | p = Path(b,source=test5)
69 | pg = PathGroup(p)
70 |
71 | pg.explore()
72 | assert len(pg.completed) == 1
73 |
74 | for q in range(6):
75 | s = pg.completed[0].state.copy()
76 | x = s.getVar('x')
77 | i = s.getVar('i')
78 | i.setTo(q)
79 | assert x.getValue() == q
80 |
81 |
82 |
83 | def test_pyObjectManager_Int_MultipleObj():
84 | b = ast_parse.parse(test4).body
85 | p = Path(b,source=test4)
86 | pg = PathGroup(p)
87 |
88 | pg.explore(find=4)
89 | assert len(pg.found) == 1
90 |
91 | pg = PathGroup(p)
92 | pg.explore(find=6)
93 |
94 | assert len(pg.found) == 1
95 |
96 | def test_pyObjectManager_Int_strPrint():
97 | b = ast_parse.parse(test3).body
98 | p = Path(b,source=test3)
99 | pg = PathGroup(p)
100 |
101 | pg.explore()
102 | assert len(pg.completed) == 1
103 |
104 | x = pg.completed[0].state.getVar('x')
105 | assert x.__str__() == "12"
106 |
107 | def test_pyObjectManager_Int_setTo():
108 | b = ast_parse.parse(test2).body
109 | p = Path(b,source=test2)
110 | pg = PathGroup(p)
111 |
112 | pg.explore()
113 | assert len(pg.completed) == 1
114 |
115 | x = pg.completed[0].state.getVar('x')
116 | y = pg.completed[0].state.getVar('y')
117 | x.setTo(1337)
118 |
119 | assert pg.completed[0].state.any_int('x') == 1337
120 | x.increment()
121 | x.setTo(y)
122 |
123 | #assert pg.completed[0].state.any_int('x') == 5
124 | assert x.getValue() == 5
125 |
126 |
127 | def test_pyObjectManager_Int_isStatic():
128 | b = ast_parse.parse(test1).body
129 | p = Path(b,source=test1)
130 | pg = PathGroup(p)
131 |
132 | pg.explore()
133 | assert len(pg.completed) == 1
134 |
135 | x = pg.completed[0].state.getVar('x')
136 |
137 | assert x.isStatic()
138 | assert x.getValue() == 1
139 |
140 |
141 |
--------------------------------------------------------------------------------
/tests/test_pyObjectManager_Real.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | x = 1.5
21 | """
22 |
23 | test2 = """
24 | x = pyState.Real()
25 | y = 5.5
26 | z = 2
27 | """
28 |
29 | test3 = """
30 | x = 6.2
31 | """
32 |
33 |
34 |
35 | def test_pyObjectManager_Real_strPrint():
36 | b = ast_parse.parse(test3).body
37 | p = Path(b,source=test3)
38 | pg = PathGroup(p)
39 |
40 | pg.explore()
41 | assert len(pg.completed) == 1
42 |
43 | x = pg.completed[0].state.getVar('x')
44 | assert x.__str__() == "6.2"
45 |
46 |
47 | def test_pyObjectManager_Real_setTo():
48 | b = ast_parse.parse(test2).body
49 | p = Path(b,source=test2)
50 | pg = PathGroup(p)
51 |
52 | pg.explore()
53 | assert len(pg.completed) == 1
54 |
55 | x = pg.completed[0].state.getVar('x')
56 | y = pg.completed[0].state.getVar('y')
57 | z = pg.completed[0].state.getVar('z')
58 |
59 | x.setTo(1337.4)
60 | assert pg.completed[0].state.any_real('x') == 1337.4
61 | x.increment()
62 | x.setTo(y)
63 | assert pg.completed[0].state.any_real('x') == 5.5
64 |
65 | x.increment()
66 | x.setTo(z)
67 | assert pg.completed[0].state.any_real('z') == 2
68 |
69 |
70 |
71 | def test_pyObjectManager_Real_isStatic():
72 | b = ast_parse.parse(test1).body
73 | p = Path(b,source=test1)
74 | pg = PathGroup(p)
75 |
76 | pg.explore()
77 | assert len(pg.completed) == 1
78 |
79 | x = pg.completed[0].state.getVar('x')
80 |
81 | assert x.isStatic()
82 | assert x.getValue() == 1.5
83 |
84 |
85 |
--------------------------------------------------------------------------------
/tests/test_pyObjectManager_String.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 | from pySym import ast_parse
10 | import z3
11 | from pySym.pyPath import Path
12 | from pySym.pyPathGroup import PathGroup
13 | import pytest
14 | from pySym.pyObjectManager.Int import Int
15 | from pySym.pyObjectManager.Real import Real
16 | from pySym.pyObjectManager.BitVec import BitVec
17 | from pySym.pyObjectManager.List import List
18 |
19 | test1 = """
20 | s = "Test"
21 | """
22 |
23 | test2 = """
24 | s = "Test"
25 | l = [x for x in s]
26 | """
27 |
28 | test3 = """
29 | s = "abcd"
30 | d = "abcd"
31 | f = "Abcd"
32 | g = pyState.String(4)
33 | """
34 |
35 | test4 = """
36 | s = "abcd"
37 | d = pyState.String(5)
38 | """
39 |
40 | def test_pyObjectManager_String_isStatic():
41 | b = ast_parse.parse(test4).body
42 | p = Path(b,source=test4)
43 | pg = PathGroup(p)
44 |
45 | pg.explore()
46 | assert len(pg.completed) == 1
47 |
48 | s = pg.completed[0].state.getVar('s')
49 | d = pg.completed[0].state.getVar('d')
50 |
51 | assert s.isStatic()
52 | assert s.getValue() == "abcd"
53 |
54 | assert not d.isStatic()
55 |
56 |
57 | def test_pyObjectManager_String_canBe_mustBe_String():
58 | b = ast_parse.parse(test3).body
59 | p = Path(b,source=test3)
60 | pg = PathGroup(p)
61 |
62 | pg.explore()
63 | assert len(pg.completed) == 1
64 |
65 | s = pg.completed[0].state.getVar('s')
66 | d = pg.completed[0].state.getVar('d')
67 | f = pg.completed[0].state.getVar('f')
68 | g = pg.completed[0].state.getVar('g')
69 |
70 | assert s.canBe(d)
71 | assert not s.canBe(f)
72 | assert g.canBe(s)
73 | assert not g.mustBe(s)
74 | assert g.canBe(f)
75 |
76 |
77 | def test_pyObjectMAnager_String_mustBe():
78 | b = ast_parse.parse(test1).body
79 | p = Path(b,source=test1)
80 | pg = PathGroup(p)
81 |
82 | pg.explore()
83 | assert len(pg.completed) == 1
84 |
85 | s = pg.completed[0].state.getVar('s')
86 |
87 | assert s.mustBe("Test")
88 | assert not s.mustBe("test")
89 |
90 |
91 | def test_pyObjectManager_String_canBe():
92 | b = ast_parse.parse(test1).body
93 | p = Path(b,source=test1)
94 | pg = PathGroup(p)
95 |
96 | pg.explore()
97 | assert len(pg.completed) == 1
98 |
99 | s = pg.completed[0].state.getVar('s')
100 |
101 | assert s.canBe("Test")
102 | assert not s.canBe("test")
103 | assert s[0:1].canBe("T")
104 | assert not s[0:2].canBe("T3")
105 | assert s[:3].canBe("Tes")
106 |
107 |
108 | def test_pyObjectManager_String_ListComp():
109 | b = ast_parse.parse(test2).body
110 | p = Path(b,source=test2)
111 | pg = PathGroup(p)
112 |
113 | pg.explore()
114 | assert len(pg.completed) == 1
115 |
116 | assert pg.completed[0].state.any_list('l') == [x for x in "Test"]
117 |
118 |
119 | def test_pyObjectManager_String_Assign():
120 | b = ast_parse.parse(test1).body
121 | p = Path(b,source=test1)
122 | pg = PathGroup(p)
123 |
124 | pg.explore()
125 | assert len(pg.completed) == 1
126 |
127 | assert pg.completed[0].state.any_str('s') == "Test"
128 |
129 |
130 |
--------------------------------------------------------------------------------
/tests/test_pyPathGroup.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 | from pySym import ast_parse
9 | import z3
10 | from pySym.pyPath import Path
11 | from pySym.pyPathGroup import PathGroup
12 |
13 | test1 = """
14 | def test2():
15 | return 5
16 |
17 | def test():
18 | return test2() + test2()
19 |
20 | x = test()
21 | z = 1
22 | """
23 |
24 | test2 = """
25 | def test():
26 | return 5 + 1.5
27 |
28 | x = test()
29 |
30 | if x > 5:
31 | x = 1
32 | else:
33 | x = 0
34 |
35 | if x == 1:
36 | x = 1337
37 |
38 | z = 1
39 | """
40 |
41 | test3 = """
42 | def test():
43 | return 5
44 |
45 | if test() == 5.0:
46 | x = 1
47 | else:
48 | x = 0
49 |
50 | q = 5
51 | """
52 |
53 | test4 = """
54 | s = "A"*16
55 |
56 | for c in s:
57 | if c == "A":
58 | q = 1
59 | else:
60 | q = 2
61 | """
62 |
63 | def test_pyPathGroup_ignore_paths():
64 | b = ast_parse.parse(test4).body
65 | p = Path(b,source=test4)
66 | pg = PathGroup(p,ignore_groups=['deadended'])
67 |
68 | # Execute to the end
69 | pg.explore()
70 |
71 | assert len(pg.completed) == 1
72 | assert len(pg.deadended) == 0
73 |
74 |
75 | def test_pyPathGroup_exploreFunctionCompare():
76 | b = ast_parse.parse(test3).body
77 | p = Path(b,source=test3)
78 | pg = PathGroup(p)
79 |
80 | # Execute to the end
81 | assert pg.explore(find=10)
82 |
83 | assert len(pg.active) == 0
84 | assert len(pg.completed) == 0
85 | assert len(pg.errored) == 0
86 | assert len(pg.deadended) == 1
87 | assert len(pg.found) == 1
88 |
89 | assert pg.found[0].state.any_int('x') == 1
90 |
91 |
92 | def test_pyPathGroup_exploreWithIf():
93 | b = ast_parse.parse(test2).body
94 | p = Path(b,source=test2)
95 | pg = PathGroup(p)
96 |
97 | # Explore to the end
98 | assert pg.explore(find=15)
99 |
100 | assert len(pg.active) == 0
101 | assert len(pg.completed) == 0
102 | assert len(pg.errored) == 0
103 | assert len(pg.deadended) == 2
104 | assert len(pg.found) == 1
105 |
106 | assert pg.found[0].state.any_int('x') == 1337
107 |
108 |
109 | def test_pyPath_exploreFindLine():
110 | b = ast_parse.parse(test1).body
111 | p = Path(b,source=test1)
112 | pg = PathGroup(p)
113 |
114 | # Explore to line 9 (z = 1)
115 | # Current setup means that z=1 will not actually be executed
116 | assert pg.explore(find=9)
117 |
118 | assert len(pg.active) == 0
119 | assert len(pg.completed) == 0
120 | assert len(pg.errored) == 0
121 | assert len(pg.deadended) == 0
122 | assert len(pg.found) == 1
123 |
124 | assert pg.found[0].state.any_int('x') == 10
125 |
126 |
127 | def test_pyPath_stepThroughProgram():
128 | b = ast_parse.parse(test1).body
129 | p = Path(b,source=test1)
130 | pg = PathGroup(p)
131 | pg.explore()
132 |
133 | assert len(pg.active) == 0
134 | assert len(pg.completed) == 1
135 | assert len(pg.errored) == 0
136 | assert len(pg.deadended) == 0
137 | assert len(pg.found) == 0
138 |
139 | assert pg.completed[0].state.any_int('x') == 10
140 | assert pg.completed[0].state.any_int('z') == 1
141 |
142 |
--------------------------------------------------------------------------------
/tests/test_pyState_Assert.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 |
4 | import logging
5 | from pySym import Colorer
6 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
7 |
8 | from pySym import ast_parse
9 | import z3
10 | from pySym.pyPath import Path
11 | from pySym.pyPathGroup import PathGroup
12 | import pySym
13 | import pytest
14 |
15 | def test_assert_compare():
16 | proj = pySym.Project(os.path.join(myPath, "scripts", "assert_script_1.py"))
17 | pg = proj.factory.path_group()
18 | pg.explore()
19 |
20 | assert len(pg.completed) == 1
21 | s = pg.completed[0].state.copy()
22 | i = s.getVar('i')
23 |
24 | # Try some values
25 | assert all([x%12==4 for x in s.any_n_int(i, 32)])
26 |
--------------------------------------------------------------------------------
/tests/test_pyState_Break.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | from pySym import ast_parse
6 | import z3
7 | from pySym.pyPath import Path
8 | import pytest
9 | from pySym.pyPathGroup import PathGroup
10 |
11 | test1 = """
12 | x = 0
13 | y = 1
14 | while x < 10:
15 | if x == 5:
16 | if y == 1:
17 | break
18 | x += 1
19 |
20 | y = 1
21 | """
22 |
23 | test2 = """
24 | out = 0
25 | q = [1,2,3,4,5]
26 | for x in q:
27 | for y in [10,11,12,13]:
28 | out += x + y
29 |
30 | if x == 3:
31 | break
32 | """
33 |
34 | def test_pySym_breakFor():
35 | b = ast_parse.parse(test2).body
36 | p = Path(b,source=test2)
37 | pg = PathGroup(p)
38 |
39 | pg.explore()
40 |
41 | assert len(pg.completed) == 1
42 | assert pg.completed[0].state.any_int('out') == 162
43 | assert pg.completed[0].state.any_int('x') == 3
44 |
45 |
46 | def test_pySym_breakWhile():
47 | b = ast_parse.parse(test1).body
48 | p = Path(b,source=test1)
49 | pg = PathGroup(p)
50 |
51 | pg.explore()
52 |
53 | assert len(pg.completed) == 1
54 | assert pg.completed[0].state.any_int('x') == 5
55 |
56 |
57 |
--------------------------------------------------------------------------------
/tests/test_pyState_For.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | import pytest
15 |
16 | test1 = """
17 | out = 0
18 | for x in [1,2,3,4,5]:
19 | out += x
20 | """
21 |
22 | test2 = """
23 | out = 0
24 | for x in [1,2,3,4,5]:
25 | for y in [10,11,12,13]:
26 | out += x + y
27 | """
28 |
29 | test3 = """
30 | out = 0
31 | q = [1,2,3,4,5]
32 | for x in q:
33 | for y in [10,11,12,13]:
34 | out += x + y
35 | """
36 |
37 | test4 = """
38 | out = 0
39 | q = [1,2,3,4,5]
40 | for x in q[:2]:
41 | for y in [10,11,12,13]:
42 | out += x + y
43 |
44 | if x == 3:
45 | break
46 | """
47 |
48 | test5 = """
49 | a = 0
50 | b = 0
51 | for x in zip([1,8],[2,3]):
52 | a += x[0]
53 | b += x[1]
54 | """
55 |
56 | def test_pySym_For_ListReturn():
57 | b = ast_parse.parse(test5).body
58 | p = Path(b,source=test5)
59 | pg = PathGroup(p)
60 |
61 | pg.explore()
62 | assert len(pg.completed) == 1
63 |
64 | assert pg.completed[0].state.any_int('a') == 9
65 | assert pg.completed[0].state.any_int('b') == 5
66 |
67 |
68 | def test_pySym_variableSlice():
69 | b = ast_parse.parse(test4).body
70 | p = Path(b,source=test4)
71 | pg = PathGroup(p)
72 |
73 | pg.explore()
74 | assert len(pg.completed) == 1
75 | assert pg.completed[0].state.any_int('out') == 104
76 |
77 |
78 | def test_pySym_variableFor():
79 | b = ast_parse.parse(test3).body
80 | p = Path(b,source=test3)
81 | pg = PathGroup(p)
82 |
83 | pg.explore()
84 | assert len(pg.completed) == 1
85 | assert pg.completed[0].state.any_int('out') == 290
86 | assert pg.completed[0].state.any_list('q') == [1,2,3,4,5]
87 |
88 |
89 | def test_pySym_nestedFor():
90 | b = ast_parse.parse(test2).body
91 | p = Path(b,source=test2)
92 | pg = PathGroup(p)
93 |
94 | pg.explore()
95 | assert len(pg.completed) == 1
96 | assert pg.completed[0].state.any_int('out') == 290
97 |
98 |
99 | def test_pySym_stupidFor():
100 | b = ast_parse.parse(test1).body
101 | p = Path(b,source=test1)
102 | pg = PathGroup(p)
103 |
104 | pg.explore()
105 | assert len(pg.completed) == 1
106 | assert pg.completed[0].state.any_int('out') == 15
107 | assert pg.completed[0].state.any_int('x') == 5
108 |
109 |
110 |
--------------------------------------------------------------------------------
/tests/test_pyState_FuncionDef.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | from pySym import ast_parse
6 | import z3
7 | from pySym.pyPath import Path
8 | import pytest
9 |
10 | test1 = """
11 | def test():
12 | x = 12
13 |
14 | def test2(a,b,c):
15 | a = 13
16 | """
17 |
18 |
19 | def test_pySym_FuncionDef():
20 | b = ast_parse.parse(test1).body
21 | p = Path(b,source=test1)
22 | # Step through program
23 | p = p.step()[0]
24 | p = p.step()[0]
25 | # We should have two defs now
26 | assert "test" in p.state.functions
27 | assert "test2" in p.state.functions
28 |
--------------------------------------------------------------------------------
/tests/test_pyState_GeneratorExp.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | import pytest
15 |
16 | test1 = """
17 | x = "".join(str(i) for i in range(5))
18 | """
19 |
20 | def test_pyState_GeneratorExp_General():
21 | b = ast_parse.parse(test1).body
22 | p = Path(b,source=test1)
23 | pg = PathGroup(p)
24 |
25 | pg.explore()
26 | assert len(pg.completed) == 1
27 | assert pg.completed[0].state.any_str('x') == "".join(str(i) for i in range(5))
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tests/test_pyState_If.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | import pytest
15 |
16 | test1 = """
17 | x = 5
18 | y = 6
19 | if x == y or 2 == 2:
20 | pass
21 | """
22 |
23 | test2 = """
24 | x = 5
25 | y = 5
26 | if x == y and y + 2 == x + 2:
27 | pass
28 | """
29 |
30 | test3 = """
31 | s = pyState.String(8)
32 | y = 0
33 | if 2 > s.index('a'):
34 | y += 1
35 | """
36 |
37 | test4 = """
38 | s = pyState.String(8)
39 | x = 5
40 | y = 6
41 | z = 0
42 | if x == y or s.index('a') == 2:
43 | z += 1
44 | """
45 |
46 | test5 = """
47 | i = pyState.Int()
48 | l = [0,i,2]
49 |
50 | x = 0
51 | y = 0
52 |
53 | if l[0]:
54 | y = 1
55 |
56 | if l[2]:
57 | y = 2
58 |
59 | if l[1]:
60 | x = 1
61 | """
62 |
63 | def test_pySym_If_Subscript_Int():
64 | b = ast_parse.parse(test5).body
65 | p = Path(b,source=test5)
66 | pg = PathGroup(p)
67 |
68 | pg.explore()
69 |
70 | # Splits into 8 possibilities and then if splits again
71 | assert len(pg.completed) == 2
72 | assert len(pg.deadended) == 2
73 |
74 | s = pg.completed[0].state.copy()
75 | x = s.getVar('x')
76 | y = s.getVar('y')
77 | i = s.getVar('i')
78 |
79 | assert y.mustBe(2)
80 |
81 | if i.mustBe(0):
82 | assert x.mustBe(0)
83 | else:
84 | assert not x.canBe(0)
85 |
86 | s = pg.completed[1].state.copy()
87 | x = s.getVar('x')
88 | y = s.getVar('y')
89 | i = s.getVar('i')
90 |
91 | assert y.mustBe(2)
92 |
93 | if i.mustBe(0):
94 | assert x.mustBe(0)
95 | else:
96 | assert not x.canBe(0)
97 |
98 |
99 | def test_pySym_If_StateSplit():
100 | b = ast_parse.parse(test3).body
101 | p = Path(b,source=test3)
102 | pg = PathGroup(p)
103 |
104 | pg.explore()
105 |
106 | # Splits into 8 possibilities and then if splits again
107 | assert len(pg.completed) == 8
108 | assert len(pg.deadended) == 8
109 |
110 | # Two of those states should hit the y+=1
111 | assert sum([p.state.any_int('y') for p in pg.completed]) == 2
112 |
113 | b = ast_parse.parse(test4).body
114 | p = Path(b,source=test4)
115 | pg = PathGroup(p)
116 |
117 | pg.explore()
118 |
119 | # Splits into 8 possibilities and then if splits again
120 | assert len(pg.completed) == 8
121 | assert len(pg.deadended) == 8
122 |
123 | # Two of those states should hit the y+=1
124 | assert sum([p.state.any_int('z') for p in pg.completed]) == 1
125 |
126 | def test_pySym_ifBoolOp():
127 | b = ast_parse.parse(test1).body
128 | p = Path(b,source=test1)
129 | pg = PathGroup(p)
130 |
131 | pg.explore()
132 |
133 | b = ast_parse.parse(test2).body
134 | p = Path(b,source=test2)
135 | pg = PathGroup(p)
136 |
137 | pg.explore()
138 |
139 |
--------------------------------------------------------------------------------
/tests/test_pyState_ListComp.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | import pytest
15 |
16 | test1 = """
17 | l = [x for x in range(5)]
18 | """
19 |
20 | test2 = """
21 | l = [x for x in [1,2,3,4,5] if x%2 == 0]
22 | """
23 |
24 | test3 = """
25 | l = [x for x in range(10) if x%2 == 0 or x%3 == 0]
26 | """
27 |
28 | test4 = """
29 | l = [x for x in [1,2,3,4,5] for y in [1,2,3]]
30 | """
31 |
32 | test5 = """
33 | l = [[x,y] for x in [1,2,3] for y in [1]]
34 | """
35 |
36 | test6 = """
37 | l = [x**2 for x in range(5)]
38 | """
39 |
40 | test7 = """
41 | s = "abcd"
42 | l = [x for x in s if x == "b"]
43 | """
44 |
45 | test8 = """
46 | l = [str(i) for i in range(10)]
47 | """
48 |
49 | def test_pyState_ListComp_MoreFunctions():
50 | b = ast_parse.parse(test8).body
51 | p = Path(b,source=test8)
52 | pg = PathGroup(p)
53 |
54 | pg.explore()
55 | assert len(pg.completed) == 1
56 | assert pg.completed[0].state.any_list('l') == [str(i) for i in range(10)]
57 |
58 |
59 | def test_pyState_ListComp_StringCmp():
60 | b = ast_parse.parse(test7).body
61 | p = Path(b,source=test7)
62 | pg = PathGroup(p)
63 |
64 | pg.explore()
65 | assert len(pg.completed) == 1
66 | assert pg.completed[0].state.any_list('l') == ["b"]
67 |
68 |
69 | def test_pyState_ListComp_outputModifier():
70 | b = ast_parse.parse(test6).body
71 | p = Path(b,source=test6)
72 | pg = PathGroup(p)
73 |
74 | pg.explore()
75 | assert len(pg.completed) == 1
76 | assert pg.completed[0].state.any_list('l') == [x**2 for x in range(5)]
77 |
78 |
79 | def test_pyState_ListComp_MultipleFor_ReturnList():
80 | b = ast_parse.parse(test5).body
81 | p = Path(b,source=test5)
82 | pg = PathGroup(p)
83 |
84 | pg.explore()
85 | assert len(pg.completed) == 1
86 | assert pg.completed[0].state.any_list('l') == [[x,y] for x in [1,2,3] for y in [1]]
87 |
88 |
89 | def test_pyState_ListComp_MultipleFor():
90 | b = ast_parse.parse(test4).body
91 | p = Path(b,source=test4)
92 | pg = PathGroup(p)
93 |
94 | pg.explore()
95 | assert len(pg.completed) == 1
96 | assert pg.completed[0].state.any_list('l') == [x for x in [1,2,3,4,5] for y in [1,2,3]]
97 |
98 | with pytest.raises(Exception):
99 | pg.completed[0].state.any_int('x')
100 |
101 |
102 | def test_pyState_ListComp_BoolComp():
103 | b = ast_parse.parse(test3).body
104 | p = Path(b,source=test3)
105 | pg = PathGroup(p)
106 |
107 | pg.explore()
108 | assert len(pg.completed) == 1
109 | assert pg.completed[0].state.any_list('l') == [x for x in range(10) if x%2 == 0 or x%3 == 0]
110 |
111 |
112 | def test_pyState_ListComp_If():
113 | b = ast_parse.parse(test2).body
114 | p = Path(b,source=test2)
115 | pg = PathGroup(p)
116 |
117 | pg.explore()
118 | assert len(pg.completed) == 1
119 | assert pg.completed[0].state.any_list('l') == [x for x in [1,2,3,4,5] if x%2 == 0]
120 |
121 |
122 | def test_pyState_ListComp_Simple():
123 | b = ast_parse.parse(test1).body
124 | p = Path(b,source=test1)
125 | pg = PathGroup(p)
126 |
127 | pg.explore()
128 | assert len(pg.completed) == 1
129 | assert pg.completed[0].state.any_list('l') == [x for x in range(5)]
130 |
131 |
--------------------------------------------------------------------------------
/tests/test_pyState_Pass.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | from pySym import ast_parse
6 | import z3
7 | from pySym.pyPath import Path
8 | import pytest
9 |
10 | test1 = """
11 | x = 4
12 | pass
13 | def test():
14 | x = 6
15 | return 5
16 |
17 | x = test()
18 | z = 1
19 | """
20 |
21 |
22 | def test_pySym_pass():
23 | # Testing we can pass :-)
24 | b = ast_parse.parse(test1).body
25 | p = Path(b,source=test1)
26 | p = p.step()[0]
27 | p = p.step()[0]
28 |
29 | assert p.state.any_int('x') == 4
30 | assert len(p.state.backtrace) == 2
31 |
32 |
33 |
--------------------------------------------------------------------------------
/tests/test_pyState_UnaryOp.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | import pytest
15 |
16 | test1 = """
17 | x = -1
18 | y = -x
19 | z = +x
20 | """
21 |
22 | def test_pySym_UnaryOp_Simple():
23 | b = ast_parse.parse(test1).body
24 | p = Path(b,source=test1)
25 | pg = PathGroup(p)
26 |
27 | pg.explore()
28 | assert len(pg.completed) == 1
29 | assert pg.completed[0].state.any_int('x') == -1
30 | assert pg.completed[0].state.any_int('y') == 1
31 | assert pg.completed[0].state.any_int('z') == -1
32 |
33 |
--------------------------------------------------------------------------------
/tests/test_pyState_While.py:
--------------------------------------------------------------------------------
1 | import sys, os
2 | myPath = os.path.dirname(os.path.abspath(__file__))
3 | #sys.path.insert(0, myPath + '/../')
4 |
5 | import logging
6 | from pySym import Colorer
7 | logging.basicConfig(level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
8 |
9 |
10 | from pySym import ast_parse
11 | import z3
12 | from pySym.pyPath import Path
13 | from pySym.pyPathGroup import PathGroup
14 | import pytest
15 | from copy import copy
16 |
17 |
18 | test1 = """
19 | x = 0
20 | while x < 10:
21 | x += 1
22 |
23 | y = 1
24 | """
25 |
26 | test2 = """
27 | def test():
28 | return 5
29 |
30 | x = 0
31 | while x < test():
32 | x += 1
33 |
34 | y = 1
35 | """
36 |
37 | test3 = """
38 | def test(x,y):
39 | return x + y
40 |
41 | x = 0
42 | z = 0
43 | while x < 5:
44 | y = 0
45 | while y < 3:
46 | z = z + test(x,y)
47 | y += 1
48 | x += 1
49 |
50 | z = z
51 | """
52 |
53 | test4 = """
54 | def test(x,y):
55 | return x + y
56 |
57 | x = 0
58 | z = 0
59 | while x < 5:
60 | y = 0
61 | while y < 3:
62 | z += test(x,y)
63 | y += 1
64 | x += 1
65 |
66 | z = z
67 | """
68 |
69 | test5 = """
70 | def test(x,y):
71 | out = 2
72 | while x < y:
73 | out *= x
74 | x += 1
75 |
76 | return out
77 |
78 | x = 0
79 | z = 0
80 | while x < 5:
81 | y = 0
82 | while y < 3:
83 | z += test(x,y)
84 | y += 1
85 | x += 1
86 |
87 | z = z
88 | """
89 |
90 | test6 = """
91 | x = 0
92 | y = 0
93 | o = 0
94 | while x < 10:
95 | while y < 5:
96 | o += 1
97 | y += 1
98 | x += 1
99 |
100 | print(o)
101 | """
102 |
103 | test7 = """
104 | s = pyState.String(3)
105 | x = 0
106 | while x < s.index('a'):
107 | x += 1
108 | """
109 |
110 |
111 | def test_pySym_While_StateSplit():
112 | # TODO: I'm not 100% sure this is right.. But can't think of why it's wrong atm...
113 | b = ast_parse.parse(test7).body
114 | p = Path(b,source=test7)
115 | pg = PathGroup(p)
116 |
117 | pg.explore()
118 | assert len(pg.completed) > 0
119 |
120 | assert set([p.state.any_int('x') for p in pg.completed]) == set([0,1,2])
121 |
122 |
123 | def test_pySym_stupidWhile():
124 | b = ast_parse.parse(test6).body
125 | p = Path(b,source=test6)
126 | pg = PathGroup(p)
127 |
128 | pg.explore()
129 | assert len(pg.completed) == 1
130 | assert pg.completed[0].state.any_int('x') == 10
131 | assert pg.completed[0].state.any_int('y') == 5
132 | assert pg.completed[0].state.any_int('o') == 5
133 |
134 |
135 | def test_pySym_complicated():
136 | b = ast_parse.parse(test5).body
137 | p = Path(b,source=test5)
138 | pg = PathGroup(p)
139 |
140 | assert pg.explore(find=19)
141 | assert pg.found[0].state.any_int('z') == 26
142 |
143 | def test_pySym_nestedWhile():
144 | b = ast_parse.parse(test3).body
145 | p = Path(b,source=test3)
146 | pg = PathGroup(p)
147 |
148 | assert pg.explore(find=14)
149 | assert pg.found[0].state.any_int('z') == 45
150 |
151 | b = ast_parse.parse(test4).body
152 | p = Path(b,source=test4)
153 | pg = PathGroup(p)
154 | assert pg.explore(find=14)
155 | assert pg.found[0].state.any_int('z') == 45
156 |
157 |
158 |
159 | def test_pySym_funcInWhileTest():
160 | b = ast_parse.parse(test2).body
161 | p = Path(b,source=test2)
162 | pg = PathGroup(p)
163 | pg.explore()
164 |
165 |
166 | assert len(pg.active) == 0
167 | assert len(pg.completed) == 1
168 | assert len(pg.errored) == 0
169 | assert len(pg.deadended) == 6
170 |
171 | assert pg.completed[0].state.any_int('x') == 5
172 |
173 |
174 | def test_pySym_simpleWhile():
175 | b = ast_parse.parse(test1).body
176 | p = Path(b,source=test1)
177 | pg = PathGroup(p)
178 | assert pg.explore(find=6)
179 |
180 | assert len(pg.active) == 0
181 | assert len(pg.completed) == 0
182 | assert len(pg.errored) == 0
183 | assert len(pg.deadended) == 11
184 | assert len(pg.found) == 1
185 |
186 | assert pg.found[0].state.isSat()
187 | assert pg.found[0].state.any_int('x') == 10
188 |
189 |
--------------------------------------------------------------------------------