import unittest from manticore.core.smtlib import ConstraintSet, solver from manticore.core.state import State from manticore.platforms import linux from manticore.models import variadic, isvariadic, strcmp, strlen class ModelMiscTest(unittest.TestCase): def test_variadic_dec(self): @variadic def f(): pass self.assertTrue(isvariadic(f)) def test_no_variadic_dec(self): def f(): pass self.assertFalse(isvariadic(f)) class ModelTest(unittest.TestCase): l = linux.SLinux('/bin/ls') state = State(ConstraintSet(), l) stack_top = state.cpu.RSP def _clear_constraints(self): self.state._constraints = ConstraintSet() def tearDown(self): self._clear_constraints() self.state.cpu.RSP = self.stack_top def _push_string(self, s): cpu = self.state.cpu cpu.RSP -= len(s) cpu.write_bytes(cpu.RSP, s) return cpu.RSP class StrcmpTest(ModelTest): _multiprocess_can_split_ = True def _push2(self, s1, s2): s1ptr = self._push_string(s1) s2ptr = self._push_string(s2) return s1ptr, s2ptr def test_concrete_eq(self): s = 'abc\0' strs = self._push2(s, s) ret = strcmp(self.state, *strs) self.assertEqual(ret, 0) def test_concrete_lt(self): def _concrete_lt(s1, s2): strs = self._push2(s1, s2) ret = strcmp(self.state, *strs) self.assertTrue(ret < 0) _concrete_lt('a\0', 'b\0') _concrete_lt('a\0', 'ab\0') def test_concrete_gt(self): def _concrete_gt(s1, s2): strs = self._push2(s1, s2) ret = strcmp(self.state, *strs) self.assertTrue(ret > 0) _concrete_gt('c\0', 'b\0') _concrete_gt('bc\0', 'b\0') def test_symbolic_actually_concrete(self): s1 = 'ab\0' s2 = self.state.symbolicate_buffer('d+\0') strs = self._push2(s1, s2) ret = strcmp(self.state, *strs) self.assertFalse(solver.can_be_true(self.state.constraints, ret >= 0)) def test_effective_null(self): s1 = self.state.symbolicate_buffer('a+') s2 = self.state.symbolicate_buffer('++') strs = self._push2(s1, s2) self.state.constrain(s1[1] == 0) self.state.constrain(s2[0] == ord('z')) ret = strcmp(self.state, *strs) self.assertFalse(solver.can_be_true(self.state.constraints, ret >= 0)) def test_symbolic_concrete(self): s1 = 'hi\0' s2 = self.state.symbolicate_buffer('+++\0') strs = self._push2(s1, s2) ret = strcmp(self.state, *strs) self.assertTrue(solver.can_be_true(self.state.constraints, ret != 0)) self.assertTrue(solver.can_be_true(self.state.constraints, ret == 0)) self.state.constrain(s2[0] == ord('a')) ret = strcmp(self.state, *strs) self.assertFalse(solver.can_be_true(self.state.constraints, ret <= 0)) self._clear_constraints() self.state.constrain(s2[0] == ord('z')) ret = strcmp(self.state, *strs) self.assertFalse(solver.can_be_true(self.state.constraints, ret >= 0)) self._clear_constraints() self.state.constrain(s2[0] == ord('h')) self.state.constrain(s2[1] == ord('i')) ret = strcmp(self.state, *strs) self.assertFalse(solver.can_be_true(self.state.constraints, ret > 0)) self.state.constrain(s2[2] == ord('\0')) ret = strcmp(self.state, *strs) self.assertFalse(solver.can_be_true(self.state.constraints, ret != 0)) class StrlenTest(ModelTest): def test_concrete(self): s = self._push_string('abc\0') ret = strlen(self.state, s) self.assertEqual(ret, 3) def test_concrete_empty(self): s = self._push_string('\0') ret = strlen(self.state, s) self.assertEqual(ret, 0) def test_symbolic_effective_null(self): sy = self.state.symbolicate_buffer('ab+') self.state.constrain(sy[2] == 0) s = self._push_string(sy) ret = strlen(self.state, s) self.assertEqual(ret, 2) def test_symbolic(self): sy = self.state.symbolicate_buffer('+++\0') s = self._push_string(sy) ret = strlen(self.state, s) self.assertItemsEqual(range(4), solver.get_all_values(self.state.constraints, ret)) self.state.constrain(sy[0] == 0) ret = strlen(self.state, s) self.assertFalse(solver.can_be_true(self.state.constraints, ret != 0)) self._clear_constraints() self.state.constrain(sy[0] != 0) self.state.constrain(sy[1] == 0) ret = strlen(self.state, s) self.assertFalse(solver.can_be_true(self.state.constraints, ret != 1)) self._clear_constraints() self.state.constrain(sy[0] != 0) self.state.constrain(sy[1] != 0) self.state.constrain(sy[2] == 0) ret = strlen(self.state, s) self.assertFalse(solver.can_be_true(self.state.constraints, ret != 2)) self._clear_constraints() self.state.constrain(sy[0] != 0) self.state.constrain(sy[1] != 0) self.state.constrain(sy[2] != 0) ret = strlen(self.state, s) self.assertFalse(solver.can_be_true(self.state.constraints, ret != 3)) def test_symbolic_mixed(self): sy = self.state.symbolicate_buffer('a+b+\0') s = self._push_string(sy) self.state.constrain(sy[1] == 0) ret = strlen(self.state, s) self.assertFalse(solver.can_be_true(self.state.constraints, ret != 1)) self._clear_constraints() self.state.constrain(sy[1] != 0) self.state.constrain(sy[3] == 0) ret = strlen(self.state, s) self.assertFalse(solver.can_be_true(self.state.constraints, ret != 3)) self._clear_constraints() self.state.constrain(sy[1] != 0) self.state.constrain(sy[3] != 0) ret = strlen(self.state, s) self.assertFalse(solver.can_be_true(self.state.constraints, ret != 4))