Skip to content

Commit

Permalink
TU for #18
Browse files Browse the repository at this point in the history
  • Loading branch information
trolldbois committed Oct 24, 2015
1 parent 973ee7a commit 7b8b517
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 36 deletions.
50 changes: 16 additions & 34 deletions haystack/basicmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ def is_valid(self, record):
def _is_valid_dynamic_constraints(self, record):
dynamic_constraints = self._get_dynamic_constraints_for(record)
if dynamic_constraints:
log.debug("dynamic constraints are %s", dynamic_constraints)
return dynamic_constraints.is_valid(record)
return True

Expand Down Expand Up @@ -194,22 +195,16 @@ def _is_valid_attr(self, attr, attrname, attrtype, record_constraints):
'basicType: %s %s %s bad value not in record_constraints[attrname]:',
attrname, attrtype, repr(attr))
return False
log.debug(
'basicType: %s %s %s ok',
attrname, attrtype, repr(attr))
log.debug('basicType: %s %s %s ok', attrname, attrtype, repr(attr))
return True
# b)
elif self._ctypes.is_struct_type(attrtype) or self._ctypes.is_union_type(attrtype):
# do i need to load it first ? becaus it should be memcopied with
# the super()..
if not self.is_valid(attr):
log.debug(
'structType: %s %s %s isValid FALSE' %
(attrname, attrtype, repr(attr)))
log.debug('structType: %s %s %s isValid FALSE', attrname, attrtype, repr(attr))
return False
log.debug(
'structType: %s %s %s isValid TRUE' %
(attrname, attrtype, repr(attr)))
log.debug('structType: %s %s %s isValid TRUE', attrname, attrtype, repr(attr))
return True
# c)
elif self._ctypes.is_array_of_basic_type(attrtype):
Expand All @@ -219,24 +214,19 @@ def _is_valid_attr(self, attr, attrname, attrtype, record_constraints):
'basicArray: %s %s %s - bad value not in record_constraints[attrname]:',
attrname, attrtype, type(attr))
return False
log.debug(
'basicArray: %s is arraytype %s we decided it was valid',
attrname,
type(attr))
log.debug('basicArray: %s is arraytype %s we decided it was valid', attrname, type(attr))
return True
# d)
elif self._ctypes.is_array_type(attrtype):
log.debug('array: %s is arraytype %s recurse validate', attrname,
repr(attr))
log.debug('array: %s is arraytype %s recurse validate', attrname, repr(attr))
attrLen = len(attr)
if attrLen == 0:
return True
elType = type(attr[0])
for i in range(0, attrLen):
# FIXME BUG DOES NOT WORK - offsetof("%s[%d]") is called,
# and %s exists, not %s[%d]
if not self._is_valid_attr(attr[i], "%s[%d]" % (attrname, i), elType,
record_constraints):
if not self._is_valid_attr(attr[i], "%s[%d]" % (attrname, i), elType, record_constraints):
return False
return True
# e)
Expand All @@ -247,21 +237,17 @@ def _is_valid_attr(self, attr, attrname, attrtype, record_constraints):
if not bool(myaddress):
if not ((None in record_constraints[attrname]) or
(0 in record_constraints[attrname])):
log.debug('str: %s %s %s isNULL - NOT EXPECTED',
attrname, attrtype, repr(attr))
log.debug('str: %s %s %s isNULL - NOT EXPECTED', attrname, attrtype, repr(attr))
return False
log.debug('str: %s %s %s isNULL - OK', attrname, attrtype,
repr(attr))
log.debug('str: %s %s %s isNULL - OK', attrname, attrtype, repr(attr))
# e.1)
return True
if (myaddress != 0 and
not self._memory_handler.is_valid_address_value(myaddress)):
log.debug('str: %s %s %s 0x%lx INVALID', attrname, attrtype,
repr(attr), myaddress)
log.debug('str: %s %s %s 0x%lx INVALID', attrname, attrtype, repr(attr), myaddress)
# e.2)
return False
log.debug('str: %s %s %s is at 0x%lx OK', attrname, attrtype,
repr(attr), myaddress)
log.debug('str: %s %s %s is at 0x%lx OK', attrname, attrtype, repr(attr), myaddress)
# e.3)
return True
# f)
Expand All @@ -270,17 +256,13 @@ def _is_valid_attr(self, attr, attrname, attrtype, record_constraints):
#log.debug('_is_valid_attr:0x%x name: %s', myaddress, attrname)
if attrname in record_constraints:
# test if NULL is an option
log.debug('self._ctypes.is_pointer_type: bool(attr):%s attr:%s',
bool(attr), attr)
log.debug('self._ctypes.is_pointer_type: bool(attr):%s attr:%s', bool(attr), attr)
if not bool(myaddress):
if not ((None in record_constraints[attrname]) or
(0 in record_constraints[attrname])):
log.debug('ptr: %s %s %s isNULL - NOT EXPECTED',
attrname, attrtype, repr(attr))
if not ((None in record_constraints[attrname]) or (0 in record_constraints[attrname])):
log.debug('ptr: %s %s %s isNULL - NOT EXPECTED', attrname, attrtype, repr(attr))
# f.1) expectedValues specifies NULL to be invalid
return False
log.debug('ptr: %s %s %s isNULL - OK', attrname, attrtype,
repr(attr))
log.debug('ptr: %s %s %s isNULL - OK', attrname, attrtype, repr(attr))
# f.2) expectedValues specifies NULL to be valid
return True
_attrType = None
Expand All @@ -291,7 +273,7 @@ def _is_valid_attr(self, attr, attrname, attrtype, record_constraints):
if (myaddress != 0 and
not self._memory_handler.is_valid_address_value(myaddress)):
log.debug('voidptr: %s %s %s 0x%lx INVALID simple pointer',
attrname, attrtype, repr(attr), myaddress)
attrname, attrtype, repr(attr), myaddress)
# f.3) address must be valid, no type requirement
return False
else:
Expand Down
1 change: 1 addition & 0 deletions haystack/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

log = logging.getLogger('utils')


class Utils(interfaces.ICTypesUtils):

def __init__(self, _target_ctypes):
Expand Down
101 changes: 99 additions & 2 deletions test/haystack/test_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import unittest

from haystack import constraints
from haystack import target
import haystack.model
from haystack import dump_loader
from haystack import basicmodel
from test.haystack import SrcTests
from test.src import ctypes6

log = logging.getLogger("test_constraints")

Expand Down Expand Up @@ -91,6 +93,101 @@ def test_read(self):
self.assertTrue(isinstance(field8, list))
self.assertEquals(field8, [0x0, 0x1, 0xff, 0xffeeffee, -0x20])


class TestConstraints6(SrcTests):

def setUp(self):
dumpname = 'test/src/test-ctypes6.64.dump'
self.memory_handler = dump_loader.load(dumpname)
self.my_model = self.memory_handler.get_model()
self.ctypes_gen64 = self.my_model.import_module("test.src.ctypes6_gen64")
# load TU values
self._load_offsets_values(self.memory_handler.get_name())
##

def tearDown(self):
self.memory_handler.reset_mappings()
self.memory_handler = None

def test_dynamic_constraints(self):

# the constraints are imposed through code.
dyna_validator = ctypes6.NodeDynamicValidator()
module_constraints = constraints.ModuleConstraints()
module_constraints.set_dynamic_constraints('struct_Node', dyna_validator)
self.validator = basicmodel.CTypesRecordConstraintValidator(self.memory_handler, module_constraints)

# should be valid.
node1 = self.offsets['test2'][0]
for instance_addr in [node1]:
m = self.memory_handler.get_mapping_for_address(instance_addr)
node = m.read_struct(instance_addr, self.ctypes_gen64.struct_Node)
self.assertTrue(self.validator.is_valid(node))

# should be invalid.
node2 = self.offsets['test3'][0] # 0xdeadbabe
items1 = self.offsets['mid_list'][0]
items2 = self.offsets['end_list'][0]
for instance_addr in [items1, items2, node2]:
m = self.memory_handler.get_mapping_for_address(instance_addr)
node = m.read_struct(instance_addr, self.ctypes_gen64.struct_Node)
self.assertFalse(self.validator.is_valid(node))

def test_dynamic_sub_constraints(self):

# the constraints are imposed through code.
# this one only accepts head and tail struct_entry values.
entry_validator = ctypes6.EntryDynamicValidator(self.memory_handler)
module_constraints = constraints.ModuleConstraints()
module_constraints.set_dynamic_constraints('struct_entry', entry_validator)
self.validator = basicmodel.CTypesRecordConstraintValidator(self.memory_handler, module_constraints)

# should be valid. its the head
node1 = self.offsets['test2'][0] # head
node2 = self.offsets['test3'][0] # tail
items1 = self.offsets['start_list'][0]
items2 = self.offsets['end_list'][0]
for instance_addr in [node1, node2, items1, items2]:
m = self.memory_handler.get_mapping_for_address(instance_addr)
node = m.read_struct(instance_addr, self.ctypes_gen64.struct_Node)
self.assertTrue(self.validator.is_valid(node))

# should be invalid.
items_mid = self.offsets['mid_list'][0]
head_first = self.offsets['head_loop_first_item'][0]
head_last = self.offsets['head_loop_last_item'][0]
for instance_addr in [items_mid, head_first, head_last]:
m = self.memory_handler.get_mapping_for_address(instance_addr)
node = m.read_struct(instance_addr, self.ctypes_gen64.struct_Node)
self.assertFalse(self.validator.is_valid(node))

def test_config_constraints(self):

# the constraints are imposed through config file.
parser = constraints.ConstraintsConfigHandler()
module_constraints = parser.read('test/src/ctypes6.constraints')
self.validator = basicmodel.CTypesRecordConstraintValidator(self.memory_handler, module_constraints)

# should be valid.
node1 = self.offsets['test2'][0]
node2 = self.offsets['test3'][0] # 0xdeadbabe
for instance_addr in [node1, node2]:
m = self.memory_handler.get_mapping_for_address(instance_addr)
node = m.read_struct(instance_addr, self.ctypes_gen64.struct_Node)
self.assertTrue(self.validator.is_valid(node))

# should be invalid.
items1 = self.offsets['mid_list'][0]
items2 = self.offsets['end_list'][0]
for instance_addr in [items1, items2]:
m = self.memory_handler.get_mapping_for_address(instance_addr)
node = m.read_struct(instance_addr, self.ctypes_gen64.struct_Node)
self.assertFalse(self.validator.is_valid(node))


if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
# logging.getLogger("constraints").setLevel(logging.DEBUG)
# logging.getLogger("basicmodel").setLevel(logging.DEBUG)
# logging.getLogger("listmodel").setLevel(logging.DEBUG)
unittest.main(verbosity=2)
28 changes: 28 additions & 0 deletions test/src/ctypes6.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-

from haystack import listmodel
from haystack.abc import interfaces


class CTypes6Validator(listmodel.ListModel):
Expand All @@ -14,3 +15,30 @@ def __init__(self, memory_handler, my_constraints, my_module):
self.register_linked_list_field_and_type(self.ctypes6.struct_Node, 'list', self.ctypes6.struct_Node, 'list')
elif self._target.get_word_size() == 8:
self.register_linked_list_field_and_type(self.ctypes6.struct_Node, 'list', self.ctypes6.struct_Node, 'list')


class NodeDynamicValidator(interfaces.IRecordTypeDynamicConstraintsValidator):
def is_valid(self, _record):
if _record.val1 != 0xdeadbeef:
return False
if _record.val2 != 0xffffffff:
return False
return True


class EntryDynamicValidator(interfaces.IRecordTypeDynamicConstraintsValidator):
"""Only validates head and tail"""
def __init__(self, memory_handler):
self.memory_handler = memory_handler
self.ctypes_utils = memory_handler.get_target_platform().get_target_ctypes_utils()

def is_valid(self, _record):
flink = self.ctypes_utils.get_pointee_address(_record.flink)
blink = self.ctypes_utils.get_pointee_address(_record.blink)
if flink == 0 and blink != 0:
# head elements
return True
if blink == 0 and flink != 0:
# tail elements
return True
return False

0 comments on commit 7b8b517

Please sign in to comment.