def run(self, thing, *args): # mMark object as symbolic if isinstance(thing, SimSootValue_ThisRef): this_ref = thing if args: method_descriptor = args[-1] else: # if args is empty, method is static and has no params method_descriptor = thing # return the appropriate value based on the return type of the method if method_descriptor is None or method_descriptor.ret is None or method_descriptor.ret == 'void': return elif method_descriptor.ret in ['byte', 'char', 'short', 'int', 'boolean']: return claripy.BVS('unc_{}_{}'.format(method_descriptor.ret, method_descriptor.name), 32) elif method_descriptor.ret == 'long': return claripy.BVS('unc_long_{}'.format(method_descriptor.name), 64) elif method_descriptor.ret == 'float': return claripy.FPS('unc_float_{}'.format(method_descriptor.name), claripy.FSORT_FLOAT) elif method_descriptor.ret == 'double': return claripy.FPS('unc_double_{}'.format(method_descriptor.name), claripy.FSORT_DOUBLE) elif method_descriptor.ret == 'java.lang.String': str_ref = SimSootValue_StringRef.new_string( self.state, claripy.StringS("unc_string_{}".format(method_descriptor.name), 1000)) return str_ref elif method_descriptor.ret.endswith('[][]'): raise NotImplementedError elif method_descriptor.ret.endswith('[]'): # TODO here array size should be symbolic return SimSootExpr_NewArray.new_array(self.state, method_descriptor.ret[:-2], claripy.BVV(2, 32)) else: obj_ref = SimSootValue_ThisRef.new_object( self.state, method_descriptor.ret, symbolic=True, init_object=False) return obj_ref
def test_ne(self): str_symb = claripy.StringS("symb_ne", 12, explicit_name=True) solver = self.get_solver() solver.add(str_symb != claripy.StringV("concrete")) self.assertTrue(solver.satisfiable()) result = solver.eval(str_symb, 4 if KEEP_TEST_PERFORMANT else 100) self.assertTrue('concrete' not in result)
def test_substr_BV_concrete_index(self): str_symbol = claripy.StringS("symb_subst", 4, explicit_name=True) solver = self.get_solver() bv1 = claripy.BVV(1, 32) bv2 = claripy.BVV(2, 32) res = claripy.StrSubstr(bv1, bv2, str_symbol) == claripy.StringV('on') solver.add(res) self.assertTrue(solver.satisfiable()) self.assertEqual('on', solver.eval(str_symbol, 1)[0][1:3])
def test_contains(self): str_symb = claripy.StringS("symb_contains", 4, explicit_name=True) res = claripy.StrContains(str_symb, claripy.StringV("an")) solver = self.get_solver() solver.add(res) self.assertTrue(solver.satisfiable()) solutions = solver.eval(str_symb, 4 if KEEP_TEST_PERFORMANT else 100) for sol in solutions: self.assertTrue('an' in sol)
def test_substr(self): str_symbol = claripy.StringS("symb_subst", 4, explicit_name=True) solver = self.get_solver() solver.add(claripy.StrSubstr(1, 2, str_symbol) == claripy.StringV('o')) self.assertTrue(solver.satisfiable()) results = solver.eval(str_symbol, 2 if KEEP_TEST_PERFORMANT else 100) self.assertEqual(len(results), 2 if KEEP_TEST_PERFORMANT else 100) for s in results: self.assertTrue(s[1:2] == 'o')
def test_congruency_2(self): ''' (set-logic ALL) (declare-fun recv_input_4_1024 () String) (assert (< ( str.indexof recv_input_4_1024 "\r\n\r\n" 0) 0)) (assert (<= 0 ( str.indexof recv_input_4_1024 " \r\n" 0))) (assert (<= 0 ( str.indexof recv_input_4_1024 " \r\n" (+ ( str.indexof recv_input_4_1024 " \r\n" 0) 1)))) (assert (<= 0 ( str.indexof recv_input_4_1024 " \r\n" (+ ( str.indexof recv_input_4_1024 " \r\n" (+ ( str.indexof recv_input_4_1024 " \r\n" 0) 1)) 1)))) (assert (= "GET" ( str.substr ( str.substr recv_input_4_1024 (+ ( str.indexof recv_input_4_1024 " \r\n" (+ ( str.indexof recv_input_4_1024 " \r\n" 0) 1)) 1) ( str.indexof recv_input_4_1024 " \r\n" (+ ( str.indexof recv_input_4_1024 " \r\n" (+ ( str.indexof recv_input_4_1024 " \r\n" 0) 1)) 1) ) ) 10 1014))) (check-sat) ''' recv_input = claripy.StringS('recv_input', 1024) constraints = [] def field_sep_idx(s, start_idx=0): return claripy.StrIndexOf(s, claripy.StringV(' \r\n'), start_idx, 32) constraints.append( claripy.StrIndexOf(recv_input, claripy.StringV('\r\n\r\n'), 0, 32) < 0) sep_idx_1 = field_sep_idx(recv_input) sep_idx_2 = field_sep_idx(recv_input, start_idx=sep_idx_1 + 1) sep_idx_3 = field_sep_idx(recv_input, start_idx=sep_idx_2 + 1) sep_idx_4 = field_sep_idx(recv_input, start_idx=sep_idx_3 + 1) constraints.append(sep_idx_1 >= 0) constraints.append(sep_idx_2 >= 0) constraints.append(sep_idx_3 >= 0) sub_start = sep_idx_2 + 1 sub_end = sep_idx_3 sub_str = claripy.StrSubstr(recv_input, sub_start, sub_end) constraints.append( claripy.StrSubstr(sub_str, 10, 1014) == claripy.StringV("GET")) results = self._collect_generic_solver_test_data((recv_input, ), constraints) self._generic_consistency_check(results) self._generic_congruency_check(results['solvers'], results)
def test_or(self): str_symb = claripy.StringS("Symb_or", 4, explicit_name=True) solver = self.get_solver() res = claripy.Or((str_symb == claripy.StringV("abc")), (str_symb == claripy.StringV("ciao"))) solver.add(res) self.assertTrue(solver.satisfiable()) result = solver.eval(str_symb, 3 if KEEP_TEST_PERFORMANT else 100) self.assertEqual({'ciao', 'abc'}, set(result))
def test_length(self): str_symb = claripy.StringS("symb_length", 12, explicit_name=True) solver = self.get_solver() # TODO: How do we want to deal with the size of a symbolic string? solver.add(claripy.StrLen(str_symb, 32) == 14) self.assertTrue(solver.satisfiable()) result = solver.eval(str_symb, 4 if KEEP_TEST_PERFORMANT else 100) for r in result: self.assertTrue(len(r) == 14)
def test_congruency_1(self): recv_input = claripy.StringS('recv_input', 1024) constraints = [] constraints.append(0 <= claripy.StrIndexOf( recv_input, claripy.StringV("\r\n\r\n"), 0, 32)) results = self._collect_generic_solver_test_data((recv_input, ), constraints) self._generic_consistency_check(results) self._generic_congruency_check(results['solvers'], results)
def test_suffix(self): str_symb = claripy.StringS("symb_suffix", 4, explicit_name=True) res = claripy.StrSuffixOf(claripy.StringV("an"), str_symb) solver = self.get_solver() solver.add(res) self.assertTrue(solver.satisfiable()) solutions = solver.eval(str_symb, 4 if KEEP_TEST_PERFORMANT else 100) for sol in solutions: self.assertTrue(sol.endswith('an'))
def test_lt_etc(self): str_symb = claripy.StringS("Symb_2", 4) solver = self.get_solver() c1 = claripy.StrLen(str_symb, 32) <= 4 c2 = claripy.StrLen(str_symb, 32) < 4 c3 = claripy.StrLen(str_symb, 32) >= 4 c4 = claripy.StrLen(str_symb, 32) > 4 solver.add(c1) solver.add(c2) solver.add(c3) solver.add(c4) self.assertFalse(solver.satisfiable())
def test_str_to_int(self): str_symb = claripy.StringS("symb_strtoint", 4, explicit_name=True) res = claripy.StrToInt(str_symb, 32) solver = self.get_solver() target_num = 12 if KEEP_TEST_PERFORMANT else 100000 solver.add(res == target_num) self.assertTrue(solver.satisfiable()) solutions = solver.eval(str_symb, 2 if KEEP_TEST_PERFORMANT else 1000000) for sol in solutions: self.assertTrue(int(sol) == target_num)
def test_is_digit(self): correct_script = '''(set-logic ALL) (declare-fun STRING_symb_str_is_digit () String) (assert (let ((.def_0 (= ( str.to.int STRING_symb_str_is_digit ) (- 1)))) (let ((.def_1 (not .def_0))) .def_1))) (check-sat) ''' str_symb = claripy.StringS("symb_str_is_digit", 12, explicit_name=True) res = claripy.StrIsDigit(str_symb) solver = self.get_solver() solver.add(res) script = solver.get_smtlib_script_satisfiability() self.assertEqual(correct_script, script)
def test_concat(self): str_concrete = claripy.StringV("conc") str_symbol = claripy.StringS("symb_concat", 4, explicit_name=True) solver = self.get_solver() res = str_concrete + str_symbol solver.add(res == claripy.StringV("concrete")) self.assertTrue(solver.satisfiable()) result = solver.eval(str_symbol, 2) self.assertEqual(1, len(result)) self.assertEqual("rete", result[0]) result = solver.eval_to_ast(str_symbol, 2) self.assertEqual([claripy.StringV("rete")], list(result))
def test_ne(self): correct_script = '''(set-logic ALL) (declare-fun {0}symb_ne () String) (assert (let ((.def_0 (= {0}symb_ne "concrete"))) (let ((.def_1 (not .def_0))) .def_1))) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_symb = claripy.StringS("symb_ne", 12, explicit_name=True) solver = self.get_solver() solver.add(str_symb != claripy.StringV("concrete")) script = solver.get_smtlib_script_satisfiability() # with open("dump_ne.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_length(self): correct_script = '''(set-logic ALL) (declare-fun {0}symb_length () String) (assert (let ((.def_0 (= (str.len {0}symb_length) 14))) .def_0)) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_symb = claripy.StringS("symb_length", 12, explicit_name=True) solver = self.get_solver() # TODO: How do we want to dela with the size of a symbolic string? solver.add(claripy.StrLen(str_symb, 32) == 14) script = solver.get_smtlib_script_satisfiability() # with open("dump_length.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_substr(self): correct_script = '''(set-logic ALL) (declare-fun {0}symb_subst () String) (assert (let ((.def_0 (= ( str.substr {0}symb_subst 1 2) "on"))) .def_0)) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_symbol = claripy.StringS("symb_subst", 4, explicit_name=True) solver = self.get_solver() res = claripy.StrSubstr(1, 2, str_symbol) == claripy.StringV('on') solver.add(res) script = solver.get_smtlib_script_satisfiability() # with open("dump_substr.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_str_to_int(self): correct_script = '''(set-logic ALL) (declare-fun {0}symb_strtoint () String) (assert (let ((.def_0 (= ( str.to.int {0}symb_strtoint ) 12))) .def_0)) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_symb = claripy.StringS("symb_strtoint", 4, explicit_name=True) res = claripy.StrToInt(str_symb, 32) solver = self.get_solver() solver.add(res == 12) script = solver.get_smtlib_script_satisfiability() # with open("dump_strtoint.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_index_of(self): correct_script = '''(set-logic ALL) (declare-fun {0}symb_suffix () String) (assert ( str.indexof {0}symb_suffix "an" 0 )) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_symb = claripy.StringS("symb_suffix", 4, explicit_name=True) res = claripy.StrIndexOf(str_symb, claripy.StringV("an"), 0, 32) solver = self.get_solver() solver.add(res) script = solver.get_smtlib_script_satisfiability() # with open("dump_suffix.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_composite_solver_with_strings(): s = claripy.SolverComposite( template_solver_string=claripy.SolverCompositeChild( backend=claripy.backend_manager.backends.smtlib_cvc4)) x = claripy.BVS("x", 32) y = claripy.BVS("y", 32) z = claripy.BVS("z", 32) str_1 = claripy.StringS("sym_str_1", 1024) c = claripy.And(x == 1, y == 2, z == 3, str_1 == claripy.StringV("cavallo")) s.add(c) nose.tools.assert_equal(len(s._solver_list), 4) nose.tools.assert_true(s.satisfiable()) nose.tools.assert_equal(list(s.eval(str_1, 1)), ["cavallo"])
def test_index_of(self): str_symb = claripy.StringS("symb_suffix", 4, explicit_name=True) res = claripy.StrIndexOf(str_symb, claripy.StringV("an"), 0, 32) solver = self.get_solver() target_idx = 4 if KEEP_TEST_PERFORMANT else 100 solver.add(res == target_idx) self.assertTrue(solver.satisfiable()) solutions = solver.eval(str_symb, 4 if KEEP_TEST_PERFORMANT else 100) for sol in solutions: self.assertEqual('an', sol[target_idx:target_idx + 2]) self.assertEqual((target_idx, ), solver.eval(res, 2))
def test_str_extract(self): correct_script = '''(set-logic ALL) (declare-fun STRING_symb_str_extract () String) (assert (let ((.def_0 (= ( str.substr STRING_symb_str_extract 5 1) "abc"))) .def_0)) (check-sat) ''' str_symb = claripy.StringS("symb_str_extract", 12, explicit_name=True) res = claripy.StrExtract( 0, 1, claripy.StrExtract(1, 2, claripy.StrExtract(4, 8, str_symb))) solver = self.get_solver() solver.add(res == claripy.StringV("abc")) script = solver.get_smtlib_script_satisfiability() # with open("dump_strextract.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_or(self): correct_script = '''(set-logic ALL) (declare-fun {0}Symb_or () String) (assert (let ((.def_0 (= {0}Symb_or "ciao"))) (let ((.def_1 (= {0}Symb_or "abc"))) (let ((.def_2 (or .def_1 .def_0))) .def_2)))) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_symb = claripy.StringS("Symb_or", 4, explicit_name=True) solver = self.get_solver() res = claripy.Or((str_symb == claripy.StringV("abc")), (str_symb == claripy.StringV("ciao"))) solver.add(res) script = solver.get_smtlib_script_satisfiability() # with open("dump_or.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_concat(self): correct_script = '''(set-logic ALL) (declare-fun {0}symb_concat () String) (assert (let ((.def_0 (str.++ "conc" {0}symb_concat))) (let ((.def_1 (= .def_0 "concrete"))) .def_1))) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_concrete = claripy.StringV("conc") str_symbol = claripy.StringS("symb_concat", 4, explicit_name=True) solver = self.get_solver() res = str_concrete + str_symbol solver.add(res == claripy.StringV("concrete")) script = solver.get_smtlib_script_satisfiability() # with open("dump_concat.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_substr_BV_symbolic_index(self): str_symbol = claripy.StringS("symb_subst", 4, explicit_name=True) solver = self.get_solver() start = claripy.BVS("start_idx", 32) count = claripy.BVS("count", 32) res = claripy.StrSubstr(start, count, str_symbol) == claripy.StringV('on') solver.add(res) self.assertTrue(solver.satisfiable()) self.assertEqual( 'on', solver.eval(str_symbol, 1, extra_constraints=(start == 0, count == 2))[0][0:2]) self.assertEqual( 'on', solver.eval(str_symbol, 1, extra_constraints=(start == 1, count == 2))[0][1:3]) self.assertEqual( 'on', solver.eval(str_symbol, 1, extra_constraints=(start == 2, count == 2))[0][2:4]) self.assertEqual( 'on', solver.eval(str_symbol, 1, extra_constraints=(start == 2, count == 3))[0][2:4]) self.assertEqual( 'on', solver.eval(str_symbol, 1, extra_constraints=(start == 2, count == 4))[0][2:4]) self.assertEqual( 'on', solver.eval(str_symbol, 1, extra_constraints=(start == 0, count == 3))[0]) self.assertEqual( 'on', solver.eval(str_symbol, 1, extra_constraints=(start == 1, count == 4))[0][1:])
def test_substr_BV_mixed_index(self): correct_script = '''(set-logic ALL) (declare-fun {0}symb_subst () String) (declare-fun symb_subst_start_idx () Int) (assert (let ((.def_0 (= ( str.substr {0}symb_subst symb_subst_start_idx 2) "on"))) .def_0)) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_symbol = claripy.StringS("symb_subst", 4, explicit_name=True) solver = self.get_solver() bv1 = claripy.BVS("symb_subst_start_idx", 32, explicit_name=True) bv2 = claripy.BVV(2, 32) res = claripy.StrSubstr(bv1, bv2, str_symbol) == claripy.StringV('on') solver.add(res) script = solver.get_smtlib_script_satisfiability() # with open("dump_substr_bv_symbolic.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_replace(self): str_to_replace_symb = claripy.StringS("symb_repl", 4, explicit_name=True) sub_str_to_repl = claripy.StringV("a") replacement = claripy.StringV("b") solver = self.get_solver() repl_stringa = claripy.StrReplace(str_to_replace_symb, sub_str_to_repl, replacement) solver.add(repl_stringa == claripy.StringV("cbne")) self.assertTrue(solver.satisfiable()) result = solver.eval(repl_stringa, 2) self.assertEqual(list(result), ["cbne"]) result = solver.eval(str_to_replace_symb, 2 if KEEP_TEST_PERFORMANT else 100) self.assertEqual(set(result), {"cbne", "cane"})
def test_index_of_symbolic_start_idx(self): str_symb = claripy.StringS("symb_index_of", 4, explicit_name=True) start_idx = claripy.BVS("symb_start_idx", 32, explicit_name=True) solver = self.get_solver() solver.add(start_idx > 32) solver.add(start_idx < 35) res = claripy.StrIndexOf(str_symb, claripy.StringV("an"), start_idx, 32) solver.add(res != -1) solver.add(res < 38) self.assertTrue(solver.satisfiable()) self.assertEqual({33, 34, 35, 36, 37}, set(solver.eval(res, 10))) strs = solver.eval(str_symb, 10 if KEEP_TEST_PERFORMANT else 100) for s in strs: self.assertTrue(32 < s.index('an') < 38)
def test_replace(self): correct_script = '''(set-logic ALL) (declare-fun {0}symb_repl () String) (assert (let ((.def_0 (= ( str.replace {0}symb_repl "a" "b" ) "cbne"))) .def_0)) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_to_replace_symb = claripy.StringS("symb_repl", 4, explicit_name=True) sub_str_to_repl = claripy.StringV("a") replacement = claripy.StringV("b") solver = self.get_solver() repl_stringa = claripy.StrReplace(str_to_replace_symb, sub_str_to_repl, replacement) solver.add(repl_stringa == claripy.StringV("cbne")) script = solver.get_smtlib_script_satisfiability() # with open("dump_replace.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)
def test_lt_etc(self): correct_script = '''(set-logic ALL) (declare-fun {0}Symb_lt_test () String) (assert (let ((.def_0 (<= (str.len {0}Symb_lt_test) 4))) .def_0)) (assert (let ((.def_0 (< (str.len {0}Symb_lt_test) 4))) .def_0)) (assert (let ((.def_0 (<= 4 (str.len {0}Symb_lt_test)))) .def_0)) (assert (let ((.def_0 (< 4 (str.len {0}Symb_lt_test)))) .def_0)) (check-sat) '''.format(String.STRING_TYPE_IDENTIFIER) str_symb = claripy.StringS("Symb_lt_test", 4, explicit_name=True) solver = self.get_solver() c1 = claripy.StrLen(str_symb, 32) <= 4 c2 = claripy.StrLen(str_symb, 32) < 4 c3 = claripy.StrLen(str_symb, 32) >= 4 c4 = claripy.StrLen(str_symb, 32) > 4 solver.add(c1) solver.add(c2) solver.add(c3) solver.add(c4) script = solver.get_smtlib_script_satisfiability() # with open("dump_lt_etc.smt2", "w") as dump_f: # dump_f.write(script) self.assertEqual(correct_script, script)