Revision ad797ce7f8c1b6f92c47e21e0cf3798c47134ad7 authored by yan on 11 September 2018, 21:32:40 UTC, committed by yan on 11 September 2018, 21:32:40 UTC
1 parent 3ff1d46
test_lazy_memory.py
from io import BytesIO
from manticore.core.smtlib import Solver, Operators
from manticore.core.smtlib.expression import *
from manticore.core.smtlib.visitors import *
import unittest
import tempfile
import os
import gc
import pickle
import fcntl
import resource
from itertools import *
import sys
from manticore.core.memory import *
from manticore.utils.helpers import issymbolic
class LazyMemoryTest(unittest.TestCase):
_multiprocess_can_split_ = True
def test_basic(self):
cs = ConstraintSet()
mem = LazySMemory32(cs)
mem.mmap(0, 4096, 'rwx', name='map')
m = mem.maps.pop()
self.assertIsInstance(m, AnonMap)
self.assertEqual(m.name, 'map')
def test_read(self):
cs = ConstraintSet()
mem = LazySMemory32(cs)
mem.mmap(0, 4096, 'rwx', name='map')
val_mapped = mem.read(0, 4)
for val in val_mapped:
self.assertIsInstance(val, bytes)
with self.assertRaises(InvalidMemoryAccess):
mem.read(8096, 4)
def test_sym_read_mapped(self):
cs = ConstraintSet()
mem = LazySMemory32(cs)
mem.mmap(0, 4096, 'rwx', name='map')
addr = cs.new_bitvec(32)
# constrain on a boundary
cs.add(addr >= 0xffc)
cs.add(addr < 0x1002)
# Ensure that all valid derefs are within mapped memory
with cs as new_cs:
new_cs.add(mem.valid_ptr(addr))
vals = solver.get_all_values(new_cs, addr)
self.assertGreater(len(vals), 0)
for v in vals:
print(v)
self.assertTrue(0 <= v < 4096)
# Ensure that all invalid derefs are outside of mapped memory
with cs as new_cs:
new_cs.add(mem.invalid_ptr(addr))
vals = solver.get_all_values(new_cs, addr)
self.assertGreater(len(vals), 0)
for v in vals:
self.assertFalse(0 <= v < 4096)
val = mem.read(addr, 1)[0]
self.assertIsInstance(val, Expression)
def test_lazysymbolic_basic_constrained_read(self):
cs = ConstraintSet()
mem = LazySMemory32(cs)
sym = cs.new_bitvec(32)
cs.add(sym.uge(0xfff))
cs.add(sym.ule(0x1010))
# Make sure reading with no mappings raises an issue
self.assertRaises(MemoryException, mem.__getitem__, 0x1000)
first = mem.mmap(0x1000, 0x1000, 'rw')
self.assertEqual(first, 0x1000)
mem.write(0x1000, b'\x00')
self.assertEqual(solver.get_all_values(cs, mem[0x1000]), [b'\x00'])
def test_arraymap(self):
m = ArrayMap(0x1000, 0x1000, 'rwx', 32)
head, tail = m.split(0x1800)
self.assertEqual(head.start, 0x1000)
self.assertEqual(tail.start, 0x1800)
self.assertEqual(len(head), 0x800)
self.assertEqual(len(tail), 0x800)
self.assertEquals(head.perms, m.perms)
self.assertEquals(tail.perms, m.perms)
reduced = m.__reduce__()
self.assertIs(reduced[0], ArrayMap)
sel = m[0x1]
self.assertIsInstance(sel, ArraySelect)
pre_array = m._array.array
m[0x1] = 1
post_array = m._array.array
self.assertIsNot(pre_array, post_array)
def test_lazysymbolic_mmapfile(self):
mem = LazySMemory32(ConstraintSet())
#start with no maps
self.assertEqual(len(mem.mappings()), 0)
rwx_file = tempfile.NamedTemporaryFile('w+b', delete=False)
rwx_file.file.write(b'a' * 0x1001)
rwx_file.close()
addr_a = mem.mmapFile(0, 0x1000, 'rwx', rwx_file.name)
self.assertEqual(len(mem.mappings()), 1)
self.assertEqual(mem[addr_a], b'a')
self.assertEqual(mem[addr_a + 0x1000 // 2], b'a')
self.assertEqual(mem[addr_a + (0x1000 - 1)], b'a')
self.assertRaises(MemoryException, mem.__getitem__, addr_a + (0x1000))
rwx_file = tempfile.NamedTemporaryFile('w+b', delete=False)
rwx_file.file.write(b'b' * 0x1001)
rwx_file.close()
addr_b = mem.mmapFile(0, 0x1000, 'rw', rwx_file.name)
self.assertEqual(len(mem.mappings()), 2)
self.assertEqual(mem[addr_b], b'b')
self.assertEqual(mem[addr_b + (0x1000 // 2)], b'b')
self.assertEqual(mem[addr_b + (0x1000 - 1)], b'b')
rwx_file = tempfile.NamedTemporaryFile('w+b', delete=False)
rwx_file.file.write(b'c' * 0x1001)
rwx_file.close()
addr_c = mem.mmapFile(0, 0x1000, 'rx', rwx_file.name)
self.assertEqual(len(mem.mappings()), 3)
self.assertEqual(mem[addr_c], b'c')
self.assertEqual(mem[addr_c + (0x1000 // 2)], b'c')
self.assertEqual(mem[addr_c + (0x1000 - 1)], b'c')
rwx_file = tempfile.NamedTemporaryFile('w+b', delete=False)
rwx_file.file.write(b'd' * 0x1001)
rwx_file.close()
addr_d = mem.mmapFile(0, 0x1000, 'r', rwx_file.name)
self.assertEqual(len(mem.mappings()), 4)
self.assertEqual(mem[addr_d], b'd')
self.assertEqual(mem[addr_d + (0x1000 // 2)], b'd')
self.assertEqual(mem[addr_d + (0x1000 - 1)], b'd')
rwx_file = tempfile.NamedTemporaryFile('w+b', delete=False)
rwx_file.file.write(b'e' * 0x1001)
rwx_file.close()
addr_e = mem.mmapFile(0, 0x1000, 'w', rwx_file.name)
self.assertEqual(len(mem.mappings()), 5)
self.assertRaises(MemoryException, mem.__getitem__, addr_e)
self.assertRaises(MemoryException, mem.__getitem__, addr_e + (0x1000 // 2))
self.assertRaises(MemoryException, mem.__getitem__, addr_e + (0x1000 - 1))
def test_lazysymbolic_map_containing(self):
cs = ConstraintSet()
mem = LazySMemory32(cs)
valid = cs.new_bitvec(32)
invalid = cs.new_bitvec(32)
mem.mmap(0x1000, 0x1000, 'rw')
m = list(mem._maps)[0]
cs.add(valid > 0x1000)
cs.add(valid < 0x1002)
cs.add(invalid < 0x1000)
ret = mem._deref_can_succeed(m, valid, 1)
self.assertTrue(ret)
ret = mem._deref_can_succeed(m, invalid, 1)
self.assertFalse(ret)
ret = mem._deref_can_succeed(m, 0x1000, 1)
self.assertTrue(ret)
ret = mem._deref_can_succeed(m, 0x800, 1)
self.assertFalse(ret)
@unittest.skip("Disabled because it takes 4+ minutes; get_all_values() isn't returning all possible addresses")
def test_lazysymbolic_constrained_deref(self):
cs = ConstraintSet()
mem = LazySMemory32(cs)
mem.page_bit_size = 12
Size = 0x1000
PatternSize = 0x100
Constant = 0x48
ConstantMask = 0xff
if False:
mem.page_bit_size = 10
Size = 0x800
PatternSize = 0x80
Constant = 0x48
ConstantMask = 0xff
first = mem.mmap(Size, Size, 'rw')
# Fill with increasing bytes
mem.write(first, bytes(islice(cycle(range(PatternSize)), Size)))
sym = cs.new_bitvec(32)
#cs.add(mem.valid_ptr(sym))
vals = mem.read(sym, 4)
# print("sym:")
# print(translate_to_smtlib(sym))
cs.add(vals[0] == Constant)
cs.add(vals[1] == (Constant + 1))
# print("\nvals:")
# print(translate_to_smtlib(cs))
possible_addrs = solver.get_all_values(cs, sym)
print("possible addrs: ", [hex(a) for a in sorted(possible_addrs)])
for i in possible_addrs:
self.assertTrue((i & ConstantMask) == Constant)
# There are 16 spans with 0x48 in [0x1000, 0x2000]
self.assertEqual(len(possible_addrs), Size // PatternSize)
if __name__ == '__main__':
unittest.main()
Computing file changes ...