def test_subgroup_family(self): cf = Permutation.read_cycle_form a = cf([[2,3],[4,6],[5,8],[9,11]], 13) b = cf([[1,2,4,7,9,3,5,6,8,10,11,12,13]], 13) fam = Refinement([SubgroupFamily(PermGroup([a,b]))]) stack = PartitionStack([0]*13,[-1]*13) stack.extend(0,[1,3,5,7,9,11]) stack.extend(1,[1]) stack.extend(1,[3]) _,_,func1 = fam.extend(stack,None) after = Partition([[4,6,8,10,13],[5,7,9,11],[1],[3],[2,12]]) self.assertEqual(stack[-1],after) stack.extend(1,[5]) fam.extend(stack,None) fam.extend(stack,None) fam.extend(stack,None) fam.extend(stack,None) fam.extend(stack,None) fam.extend(stack,None) self.assertFalse(stack.discrete()) fam.extend(stack,None) self.assertTrue(stack.discrete()) right_before = PartitionStack.single_partition_stack([[2,4,6,8,10,12,13],[1,5,7,11],[9],[3]]) func1(right_before) right_after = Partition([[2,6,8,12,13],[1,5,7,11],[9],[3],[4,10]]) self.assertEqual(right_before[-1],right_after)
def test_partition_stabaliser(self): fam = Refinement([PartitionStabaliserFamily(Partition([[1,2],[3,4]]))]) a = PartitionStack([0,0,0,0],[-1,-1,-1,-1]) b = PartitionStack([0,0,0,0],[-1,-1,-1,-1]) _,_, func = fam.extend(a,b) c = PartitionStack([0,0,0,0],[-1,-1,-1,-1]) d = PartitionStack([0,0,0,0],[-1,-1,-1,-1]) func(c,d) self.assertEqual((a,b),(c,d)) _,_,func2 = fam.extend(a,b) self.assertTrue(func2 == None) self.assertEqual((a,b),(c,d))
def test_partition_stabaliser_with_none(self): stab = Partition([[1],[2],[3,4]]) fam = Refinement([PartitionStabaliserFamily(stab)]) a = PartitionStack([0,0,0,0],[-1,-1,-1,-1]) b = PartitionStack([0,0,0,0],[-1,-1,-1,-1]) _,_,func1 = fam.extend(a,None) _,_,func2 = fam.extend(a,None) _,_,func3 = fam.extend(a,None) self.assertTrue(func3 == None) func1(None,b) func2(None,b) self.assertEqual(a,b) self.assertEqual(len(a[-1]),3) self.assertEqual(sorted(stab), sorted(a[-1]))
def test_refinement_init(self): fam = Refinement([IdentityFamily()]) triple = fam.extend(None,None) self.assertEqual(triple,(None,None,None)) a = PartitionStack([0,0,0,0,0],[-1,-1,-1,-1,-1]) b = PartitionStack([0,1,1,1,0],[-1,0,0,0,-1]) triple = fam.extend(a,None) self.assertEqual(triple,(a,None,None)) triple = fam.extend(None,b) self.assertEqual(triple,(None,b,None)) triple = fam.extend(a,b) self.assertEqual(triple,(a,b,None)) self.assertEqual(a, PartitionStack([0,0,0,0,0],[-1,-1,-1,-1,-1])) self.assertEqual(b, PartitionStack([0,1,1,1,0],[-1,0,0,0,-1]))
slither = Slither('data_dependency_simple_example.sol') myContract = slither.get_contract_from_name('MyContract') funcA = myContract.get_function_from_signature('foo()') a = myContract.get_state_variable_from_name('a') b = myContract.get_state_variable_from_name('b') c = myContract.get_state_variable_from_name('c') d = myContract.get_state_variable_from_name('d') D = Dependency() D.compute_contract(myContract, slither) D.dependencies = funcA.context[D.KEY_NON_SSA] R = Refinement() R.compute_contract(myContract, slither) guards = [] for var in R.types[R.Typ.GUARD]: if var in D.dependencies: guards += D.dependencies[var] R.types[R.Typ.GUARD] += guards for typ in R.types: for var in R.types[typ]: if var.name.startswith("REF") or var.name.startswith("TMP"): R.types[typ].remove(var) to_delete = []
def analyze(fname, cname='MyContract', funcname='foo()'): slither = Slither(fname) myContract = slither.get_contract_from_name(cname) funcA = myContract.get_function_from_signature(funcname) # Dependency Analysis D = Dependency() D.compute_contract(myContract, slither) D.dependencies = funcA.context[D.KEY_NON_SSA] # Refinement Analysis R = Refinement() R.compute_contract(myContract, slither, fname) # Lambda Analysis lambdas = get_lambda_analysis(fname, myContract, slither) # For Guard Types, use Dependency Analysis to fetch all vars which affect # the Guard (i.e. on which the guard depends) guards = [] for var in R.types[R.Typ.GUARD]: if var in D.dependencies: guards += D.dependencies[var] R.types[R.Typ.GUARD] += guards # Remove temporary variables and ref vars from types to_delete = {} for typ in R.types: to_delete[typ] = [] if typ != 6 and typ != 7: for var in R.types[typ]: if var.name.startswith("REF") or var.name.startswith("TMP"): to_delete[typ].append(var) for k,vals in to_delete.items(): for v in vals: R.types[k].remove(v) # Remove temporary variables and ref vars from dependencies to_delete = [] for var in D.dependencies: if var.name.startswith("REF") or var.name.startswith("TMP"): to_delete.append(var) else: to_delete2 = [] for var2 in D.dependencies[var]: if var2.name.startswith("REF") or var2.name.startswith("TMP"): to_delete2.append(var2) for x in to_delete2: D.dependencies[var].remove(x) if len(D.dependencies[var]) == 0: to_delete.append(var) for x in to_delete: D.dependencies.pop(x, None) # Fetch written and read types from dependencies R.types[R.Typ.WRITTEN] += D.dependencies.keys() R.types[R.Typ.READ] += [x for vals in D.dependencies.values() for x in vals] # Anything that is an index or guard is also read R.types[R.Typ.READ] += R.types[R.Typ.INDEX] R.types[R.Typ.READ] += R.types[R.Typ.GUARD] R.types[R.Typ.READ] += R.types[R.Typ.GUARDSTART] R.types[R.Typ.READ] += R.types[R.Typ.GUARDEND] # Reformat refinement type entries R_types_formatted = {} for typ, vrs in R.types.items(): # Special check for lower casing True and False constants rhs = set(map(lambda v: v.lower() if v=="True" or v=="False" else v, set(map(str, vrs)))) typ = typ.lower() if typ == "True" or typ == "False" else typ R_types_formatted[typ] = rhs R.types = R_types_formatted # Reformat dependencies entries dependencies_formatted = {} for v, vrs in D.dependencies.items(): # Special check for lower casing True and False constants lhs = str(v).lower() if str(v) == "True" or str(v) == "False" else str(v) rhs = set(map(lambda v: v.lower() if v=="True" or v=="False" else v, set(map(str, vrs)))) dependencies_formatted[lhs] = rhs D.dependencies = dependencies_formatted # Add lambdas to dependencies based on sub-parts dependencies_lambdas = {} for v, vrs in D.dependencies.items(): dependencies_lambdas[v] = vrs for lam in lambdas: lam_vrs = re.findall(r"[\w']+", lam[lam.index(":")+1:]) if any(map(lambda lv: lv in vrs, lam_vrs)): dependencies_lambdas[v].add(lam) D.dependencies = dependencies_lambdas # # Transitive Closure of Dependencies # D.dependencies = transitive_close(D.dependencies) return D, R