Catch and refactor MemoryExceptions (#370)
* initial
* Clean, only store address in message if not symbolic
If it's symbolic,it renders like
Generating testcase No. 2 - Invalid symbolic memory access (mode:r) <<manticore.core.smtlib.expression.BitVecAnd object at 0x7fd6dcd14410>>
which is not useful output to the user.
* Format as hex
* Fix tests
* Rm comments
This commit is contained in:
@@ -479,12 +479,6 @@ class Executor(object):
|
||||
current_state = None
|
||||
|
||||
except TerminateState as e:
|
||||
#logger.error("MemoryException at PC: 0x{:016x}. Cause: {}\n".format(current_state.cpu.instruction.address, e.cause))
|
||||
#self.generate_testcase(current_state, "Memory Exception: " + str(e))
|
||||
#self.generate_testcase(current_state, "Invalid PC Exception" + str(e))
|
||||
#self.generate_testcase(current_state, "Program finished correctly")
|
||||
#logger.error("Syscall not implemented: %s", str(e))
|
||||
|
||||
#Notify this worker is done
|
||||
self.will_terminate_state(current_state, current_state_id, e)
|
||||
|
||||
|
||||
+38
-30
@@ -8,38 +8,25 @@ from ..utils.helpers import issymbolic
|
||||
|
||||
logger = logging.getLogger('MEMORY')
|
||||
|
||||
|
||||
class MemoryException(Exception):
|
||||
'''
|
||||
Memory exceptions
|
||||
'''
|
||||
def __init__(self, cause, address):
|
||||
def __init__(self, message, address=None):
|
||||
'''
|
||||
Builds a memory exception.
|
||||
|
||||
:param cause: exception message.
|
||||
:param message: exception message.
|
||||
:param address: memory address where the exception occurred.
|
||||
'''
|
||||
super(MemoryException, self, ).__init__('{} <{}>'.format(cause, address))
|
||||
self.cause = cause
|
||||
self.address = address
|
||||
self.message = message
|
||||
if address is not None and not issymbolic(address):
|
||||
self.message += ' <{:x}>'.format(address)
|
||||
|
||||
def __str__(self):
|
||||
return '%s <%s>'%(self.cause, '%08x'%self.address)
|
||||
|
||||
class InvalidMemoryAccess(MemoryException):
|
||||
def __init__(self, address, mode):
|
||||
self.mode = mode
|
||||
super(InvalidMemoryAccess, self, ).__init__('Invalid mode trying to access memory in mode {}'.format(mode), address)
|
||||
|
||||
class InvalidSymbolicMemoryAccess(InvalidMemoryAccess):
|
||||
def __init__(self, cause, address, size, constraint):
|
||||
super(InvalidSymbolicMemoryAccess, self, ).__init__(cause, address)
|
||||
#the crashing constraint you need to assert
|
||||
self.constraint = constraint
|
||||
self.size = size
|
||||
|
||||
def __str__(self):
|
||||
return '%s <%s>'%(self.cause, repr(self.address))
|
||||
return self.message
|
||||
|
||||
|
||||
class ConcretizeMemory(MemoryException):
|
||||
@@ -53,6 +40,28 @@ class ConcretizeMemory(MemoryException):
|
||||
self.size = size
|
||||
self.policy = policy
|
||||
|
||||
|
||||
class InvalidMemoryAccess(MemoryException):
|
||||
_message = 'Invalid memory access'
|
||||
|
||||
def __init__(self, address, mode):
|
||||
assert mode in 'rwx'
|
||||
suffix = ' (mode:{})'.format(mode)
|
||||
message = self._message + suffix
|
||||
super(InvalidMemoryAccess, self, ).__init__(message, address)
|
||||
self.mode = mode
|
||||
|
||||
|
||||
class InvalidSymbolicMemoryAccess(InvalidMemoryAccess):
|
||||
_message = 'Invalid symbolic memory access'
|
||||
|
||||
def __init__(self, address, mode, size, constraint):
|
||||
super(InvalidSymbolicMemoryAccess, self, ).__init__(address, mode)
|
||||
#the crashing constraint you need to assert
|
||||
self.constraint = constraint
|
||||
self.size = size
|
||||
|
||||
|
||||
class Map(object):
|
||||
'''
|
||||
A memory map.
|
||||
@@ -501,7 +510,7 @@ class Memory(object):
|
||||
return p << self.page_bit_size
|
||||
counter+=1
|
||||
if counter >= self.memory_size/self.page_size:
|
||||
raise MemoryException('Not enough memory', 0)
|
||||
raise MemoryException('Not enough memory')
|
||||
|
||||
return self._search( size, self.memory_size-size, counter )
|
||||
|
||||
@@ -752,7 +761,7 @@ class Memory(object):
|
||||
#write and read potentially symbolic bytes at symbolic indexes
|
||||
def read(self, addr, size):
|
||||
if not self.access_ok(slice(addr, addr+size), 'r'):
|
||||
raise MemoryException('No access reading', addr)
|
||||
raise InvalidMemoryAccess(addr, 'r')
|
||||
|
||||
assert size > 0
|
||||
result = []
|
||||
@@ -806,7 +815,7 @@ class Memory(object):
|
||||
def write(self, addr, buf):
|
||||
size = len(buf)
|
||||
if not self.access_ok(slice(addr, addr + size), 'w'):
|
||||
raise MemoryException('No access writing', addr)
|
||||
raise InvalidMemoryAccess(addr, 'w')
|
||||
assert size > 0
|
||||
stop = addr + size
|
||||
start = addr
|
||||
@@ -913,10 +922,9 @@ class SMemory(Memory):
|
||||
logger.debug('Reading %d bytes from symbolic address %s', size, address)
|
||||
try:
|
||||
solutions = solver.get_all_values(self.constraints, address, maxcnt=0x1000) #if more than 0x3000 exception
|
||||
except TooManySolutions, e:
|
||||
except TooManySolutions as e:
|
||||
m, M = solver.minmax(self.constraints, address)
|
||||
logger.info('Got TooManySolutions on a symbolic read. Range [%x, %x]. Not crashing!', m, M)
|
||||
logger.info('Memory:%s', self)
|
||||
logger.debug('Got TooManySolutions on a symbolic read. Range [%x, %x]. Not crashing!', m, M)
|
||||
|
||||
crashing_condition = True
|
||||
for start, end, perms, offset, name in self.mappings():
|
||||
@@ -925,7 +933,7 @@ class SMemory(Memory):
|
||||
crashing_condition = Operators.AND(Operators.OR( (address+size).ult(start), address.uge(end) ), crashing_condition)
|
||||
|
||||
if solver.can_be_true(self.constraints, crashing_condition):
|
||||
raise InvalidSymbolicMemoryAccess('No access reading symbolic', address, size, crashing_condition)
|
||||
raise InvalidSymbolicMemoryAccess(address, 'r', size, crashing_condition)
|
||||
|
||||
|
||||
#INCOMPLETE Result! We could also fork once for every map
|
||||
@@ -945,7 +953,7 @@ class SMemory(Memory):
|
||||
crashing_condition = Operators.OR(address == base, crashing_condition)
|
||||
|
||||
if solver.can_be_true(self.constraints, crashing_condition):
|
||||
raise InvalidSymbolicMemoryAccess('No access reading symbolic', address, size, crashing_condition)
|
||||
raise InvalidSymbolicMemoryAccess(address, 'r', size, crashing_condition)
|
||||
|
||||
condition = False
|
||||
for base in solutions:
|
||||
@@ -997,7 +1005,7 @@ class SMemory(Memory):
|
||||
crashing_condition = Operators.OR(address == base, crashing_condition)
|
||||
|
||||
if solver.can_be_true(self.constraints, crashing_condition):
|
||||
raise InvalidSymbolicMemoryAccess('No access writing symbolic', address, size, crashing_condition)
|
||||
raise InvalidSymbolicMemoryAccess(address, 'w', size, crashing_condition)
|
||||
|
||||
for offset in xrange(size):
|
||||
for base in solutions:
|
||||
@@ -1009,7 +1017,7 @@ class SMemory(Memory):
|
||||
for offset in xrange(size):
|
||||
if issymbolic(value[offset]):
|
||||
if not self.access_ok(address+offset, 'w'):
|
||||
raise MemoryException('No access writing', address+offset)
|
||||
raise InvalidMemoryAccess(address+offset, 'w')
|
||||
self._symbols[address+offset] = [(True, value[offset])]
|
||||
else:
|
||||
# overwrite all previous items
|
||||
|
||||
@@ -9,20 +9,19 @@ from ..utils.event import Signal, forward_signals
|
||||
|
||||
#import exceptions
|
||||
from .cpu.abstractcpu import ConcretizeRegister
|
||||
from .memory import ConcretizeMemory
|
||||
from .memory import ConcretizeMemory, MemoryException
|
||||
from ..platforms.platform import *
|
||||
|
||||
class StateException(Exception):
|
||||
''' All state related exceptions '''
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(StateException, self).__init__(*args)
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class TerminateState(StateException):
|
||||
''' Terminates current state exploration '''
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TerminateState, self).__init__(*args, **kwargs)
|
||||
self.testcase = kwargs.get('testcase', False)
|
||||
def __init__(self, message, testcase=False):
|
||||
super(TerminateState, self).__init__(message)
|
||||
self.testcase = testcase
|
||||
|
||||
|
||||
class Concretize(StateException):
|
||||
@@ -138,6 +137,8 @@ class State(object):
|
||||
expression=expression,
|
||||
setstate=setstate,
|
||||
policy=e.policy)
|
||||
except MemoryException as e:
|
||||
raise TerminateState(e.message, testcase=True)
|
||||
|
||||
#Remove when code gets stable?
|
||||
assert self.platform.constraints is self.constraints
|
||||
|
||||
@@ -581,7 +581,7 @@ class kernel32(object):
|
||||
try:
|
||||
key_str = readStringFromPointer(platform, cpu, lpSubKey, utf16)
|
||||
except MemoryException as me:
|
||||
raise MemoryException("{}: {}".format(myname, me.cause), 0xFFFFFFFF)
|
||||
raise MemoryException("{}: {}".format(myname, me.message), 0xFFFFFFFF)
|
||||
except SymbolicAPIArgument:
|
||||
raise ConcretizeArgument(platform.current, 1)
|
||||
|
||||
@@ -645,7 +645,7 @@ class kernel32(object):
|
||||
try:
|
||||
key_str = readStringFromPointer(platform, cpu, lpSubKey, utf16)
|
||||
except MemoryException as me:
|
||||
raise MemoryException("{}: {}".format(myname, me.cause), 0xFFFFFFFF)
|
||||
raise MemoryException("{}: {}".format(myname, me.message), 0xFFFFFFFF)
|
||||
except SymbolicAPIArgument:
|
||||
raise ConcretizeArgument(platform.current, 1)
|
||||
|
||||
@@ -744,7 +744,7 @@ class kernel32(object):
|
||||
try:
|
||||
filename = readStringFromPointer(platform, cpu, lpFileName, utf16)
|
||||
except MemoryException as me:
|
||||
msg = "CreateFile{}: {}".format(utf16 and "W" or "A", me.cause)
|
||||
msg = "CreateFile{}: {}".format(utf16 and "W" or "A", me.message)
|
||||
raise MemoryException(msg, 0xFFFFFFFF)
|
||||
except SymbolicAPIArgument:
|
||||
raise ConcretizeArgument(platform.current, 0)
|
||||
@@ -850,7 +850,7 @@ class kernel32(object):
|
||||
try:
|
||||
appname = readStringFromPointer(platform, cpu, lpApplicationName, utf16)
|
||||
except MemoryException as me:
|
||||
msg = "{}: {}".format(myname, me.cause)
|
||||
msg = "{}: {}".format(myname, me.message)
|
||||
raise MemoryException(msg, 0xFFFFFFFF)
|
||||
except SymbolicAPIArgument:
|
||||
raise ConcretizeArgument(platform.current, 0)
|
||||
@@ -858,7 +858,7 @@ class kernel32(object):
|
||||
try:
|
||||
cmdline = readStringFromPointer(platform, cpu, lpCommandLine, utf16)
|
||||
except MemoryException as me:
|
||||
msg = "{}: {}".format(myname, me.cause)
|
||||
msg = "{}: {}".format(myname, me.message)
|
||||
raise MemoryException(msg, 0xFFFFFFFF)
|
||||
except SymbolicAPIArgument:
|
||||
raise ConcretizeArgument(platform.current, 1)
|
||||
|
||||
+11
-4
@@ -1280,7 +1280,9 @@ class MemoryTest(unittest.TestCase):
|
||||
self.assertEqual(mem[addr], 'a')
|
||||
|
||||
mem.mprotect(addr, size, 'w')
|
||||
self.assertRaisesRegexp(MemoryException, "No access reading <%08x>"%addr, mem.__getitem__, addr)
|
||||
with self.assertRaisesRegexp(InvalidMemoryAccess, 'Invalid memory access \(mode:.\) <{:x}>'.format(addr)):
|
||||
_ = mem[addr]
|
||||
|
||||
|
||||
|
||||
def testmprotectFailSymbReading(self):
|
||||
@@ -1333,7 +1335,10 @@ class MemoryTest(unittest.TestCase):
|
||||
#print map(hex,sorted(solver.get_all_values(cs, x, 0x100000))), map(hex,solver.minmax(cs, x)), mem[x]
|
||||
|
||||
#No Access Reading <4160741376>
|
||||
self.assertRaisesRegexp(MemoryException, r"No access reading.*", mem.__getitem__, x)
|
||||
# self.assertRaisesRegexp(MemoryException, r"No access reading.*", mem.__getitem__, x)
|
||||
with self.assertRaisesRegexp(InvalidSymbolicMemoryAccess, 'Invalid symbolic memory access.*'.format(addr)):
|
||||
_ = mem[x]
|
||||
# mem[addr] = 'a'
|
||||
|
||||
def testmprotectFailWriting(self):
|
||||
mem = Memory32()
|
||||
@@ -1346,7 +1351,8 @@ class MemoryTest(unittest.TestCase):
|
||||
addr = mem.mmap(None, size, 'wx')
|
||||
mem[addr] = 'a'
|
||||
mem.mprotect(addr, size, 'r')
|
||||
self.assertRaisesRegexp(MemoryException, "No access writing <%08x>"%addr, mem.__setitem__, addr, 'a')
|
||||
with self.assertRaisesRegexp(InvalidMemoryAccess, 'Invalid memory access \(mode:w\) <{:x}>'.format(addr)):
|
||||
mem[addr] = 'a'
|
||||
|
||||
def testmprotecNoReadthenOkRead(self):
|
||||
mem = Memory32()
|
||||
@@ -1359,7 +1365,8 @@ class MemoryTest(unittest.TestCase):
|
||||
addr = mem.mmap(None, size, 'wx')
|
||||
mem[addr] = 'a'
|
||||
|
||||
self.assertRaisesRegexp(MemoryException, "No access reading <%08x>"%addr, mem.__getitem__, addr)
|
||||
with self.assertRaisesRegexp(InvalidMemoryAccess, 'Invalid memory access \(mode:r\) <{:x}>'.format(addr)):
|
||||
_ = mem[addr]
|
||||
|
||||
mem.mprotect(addr, size, 'r')
|
||||
self.assertEqual(mem[addr], 'a')
|
||||
|
||||
Reference in New Issue
Block a user