def __doReplaceCond(self, cond): assert(isinstance(cond, str)) tokens, z3range = parseCondition(cond) cc = ConditionContainer(isCNF=True) for token in tokens: if len(token.split("#")) != 2: # FIXME : ignore complicated conjured cases for now. return cc tokenKind, tokenExp = [x.strip() for x in token.split("#")] if tokenKind[0] != "E": cc.append(cond) continue # Now we have E kind, so let's unroll it. # Locate rc of the target function, which also has the # return value in the proper range. ftnName, args = parseConjExpr(tokenExp) conjuredCc = self.__getConditionByFunction(ftnName, args, z3range) if len(conjuredCc) == 0: # FIXME: Failed to locate the target function condition. return cc # TODO: Reppresent into DNF if there's multiple conditions. assert(len(conjuredCc) == 1) print "conjuredCc:", conjuredCc, type(conjuredCc) return cc
def __getConditionByFunction(self, ftnName, args, z3range=None): rcList = self.rcDictFtn.get(ftnName, []) if z3range == None: cc = ConditionContainer(isCNF=False) for x in rcList: if x["CONDITION"] != None: cc.append(ConditionContainer(isCNF=True, conditions = x["CONDITION"])) return cc # If z3range is given, check if the return value of condition is in # z3range. filteredRcs = [] for rc in rcList: # TODO: what if the return value is not integer type? retValue = int(rc["RETURN"]) for minValue, maxValue in z3range: if retValue >= minValue and retValue <= maxValue: filteredRcs.append(rc) break # For each condition, we should replace all arguments into # as presented in a conjured form. # That is, rcArgs are replaced with args newCc = ConditionContainer(isCNF=False) for rc in filteredRcs: newSubCc = ConditionContainer(isCNF=True) rcArgs = rc.getFunctionArgs() rcConds = rc["CONDITION"] for rcCond in rcConds: newSubCc.append(replaceConditionArgs(rcCond, rcArgs, args)) return newCc
def getConditionsByKey(self, key): l = self.rcDict.get(key,None) cc = ConditionContainer(isCNF=False) for x in l: if x["CONDITION"] != None: cc.append(ConditionContainer(isCNF=True, conditions = x["CONDITION"])) return cc
def test_isEqual(): cc1 = ConditionContainer(isCNF=True) cc1.append("(S64 # attr->ia_valid) & (I # 1) : { [0, 0] }") cc1.append("(S64 # attr->ia_valid) & (I # 8) : { [1, 4294967295] }") cc2 = ConditionContainer(isCNF=True) cc2.append("(S64 # attr->ia_valid) & (I # 1) : { [0, 0] }") cc2.append("(S64 # attr->ia_valid) & (I # 8) : { [1, 4294967295] }") cc2.append("(S64 # attr->ia_valid) & (I # 2) : { [0, 0] }") cc3 = ConditionContainer(isCNF=True) cc3.append("(S64 # attr->ia_valid) & (I # 8) : { [1, 4294967295] }") cc3.append("(S64 # attr->ia_valid) & (I # 1) : { [0, 0] }") cc4 = ConditionContainer(isCNF=True) cc4.append("(S64 # attr->ia_valid) & (I # 8) : { [1, 4294967295] }") cc5 = ConditionContainer(isCNF=True) cc5.append("(S64 # attr->ia_valid) & (I # 1) : { [0, 1] }") cc5.append("(S64 # attr->ia_valid) & (I # 8) : { [1, 4294967295] }") cc6 = ConditionContainer(isCNF=True) cc6.append("(S64 # x) : { [0,100]}") cc7 = ConditionContainer(isCNF=False) cc7.append(ConditionContainer(isCNF=True, conditions = ["(S64 # x) : { [0,100]}", "(S64 # y) : { [-9223372036854775808, -1], [1, 9223372036854775807]}",])) cc7.append(ConditionContainer(isCNF=True, conditions = ["(S64 # x) : { [0,100]}", "(S64 # y) : { [0,0]}"])) # We don't handle these cases. # cc8 = ConditionContainer(isCNF=True) # cc8.append("(S64 # (S64 # __fdget(fdout)) & (I # 3)) & (I # 1) : { [1, 4294967295] }") # cc9 = ConditionContainer(isCNF=True) # cc9.append("(S64 # (S64 # __fdget(fdout)) & (I # 3)) & (I # 1) : { [1, 4294967295] }") z3f = Z3Helper() assert(z3f.isEqual(cc1, cc1) == True) assert(z3f.isEqual(cc1, cc2) == False) assert(z3f.isEqual(cc1, cc2) == False) assert(z3f.isEqual(cc1, cc3) == True) assert(z3f.isEqual(cc1, cc4) == False) assert(z3f.isEqual(cc1, cc5) == False) assert(z3f.isEqual(cc6, cc7) == True) # assert(z3f.isEqual(cc8, cc9) == True) return