def calc_cov_heuristic( objs, parent_stack: List[str], inpt: str, knowledge: KnowledgeHandling ) -> Tuple["HeuristicValue", Set[Tuple[Any, Any]], Set[Tuple[Any, Any]]]: """ Calculates based on the covered lines and the heuristic value of the parent the heurisitic value for the children. New heuristic value is: #newly covered lines + 1 - heuristic value of parent. -1 as if no new line is covered the heuristic value decreases over time :param inpt: The string used in the execution :param objs: the covered lines and comparisons :param parent_stack: the smallest stack occurred for the parent input """ # Todo also take stackdepth into account (maybe in combination with input length s.t. for longer inputs a small stack is preferred # Todo this obviously only works for recursive parsers, but for all others this is more or less a nop tmp_events = [] coverage_events = [] stack = HeuristicValue.calc_stack(objs) all_covered = set() # we need to consider the taken branches between the last comparison and the eof comparison last_was_real = False # cur_idx = -1 for obj in objs: # consider only basic block jumps up until the last "real" comparison if Utils.is_real_input_comparison( obj, Utils.max_index - 1): # and cur_idx != int(obj["index"][0]): # last_was_eof = False coverage_events += tmp_events tmp_events = [] last_was_real = True # cur_idx = int(obj["index"][0]) elif not Utils.is_real_input_comparison( obj, Utils.max_index - 1) and obj["type"] == "INPUT_COMPARISON" and last_was_real: last_was_real = False coverage_events += tmp_events tmp_events = [] # elif obj["type"] == "INPUT_COMPARISON" and obj["operator"] == "eof" and not last_was_eof: # last_was_eof = True # coverage_events += tmp_events # tmp_events = [] elif obj["type"] == "COVERAGE_EVENT": tmp_events.append(obj) all_covered.add((obj["old"], obj["new"])) cover_counter = 0 new_covered = 0 covered = set() for event in coverage_events: value = (event["old"], event["new"]) if value not in Utils.valid_covered: cover_counter += 2 new_covered += 1 else: cover_counter += 1 / Utils.valid_covered[value] covered.add(value) same_path_taken = HeuristicValue.check_same_path_taken(coverage_events) return HeuristicValue((new_covered, cover_counter), stack, parent_stack, inpt, same_path_taken, knowledge), covered, all_covered
def _calc_tos_coverage(self, objs, tos): is_tos = False self.tos_cover_counter = 0 last_was_eof = False cur_idx = -1 tmp_events = set() for obj in objs: # consider only basic block jumps up until the last "real" comparison if obj["type"] == "INPUT_COMPARISON" and obj["operator"] == "eof": tmp_events = set() elif obj["type"] == "STACK_EVENT" and len(obj["stack"]) == len(self.min_stack_list) and obj["stack"][-1] == tos: is_tos = True elif obj["type"] == "STACK_EVENT" and obj["stack"] and obj["stack"][-1] != tos: is_tos = False elif Utils.is_real_input_comparison(obj, Utils.max_index - 1) and cur_idx != obj["index"][0]: last_was_eof = False self.tos_branches.update(tmp_events) tmp_events = set() cur_idx = int(obj["index"][0]) elif obj["type"] == "INPUT_COMPARISON" and obj["operator"] == "eof" and not last_was_eof: last_was_eof = True self.tos_branches.update(tmp_events) tmp_events = set() elif is_tos and obj["type"] == "COVERAGE_EVENT": tmp_events.add((obj["old"], obj["new"])) self.tos_cover_counter = len(self.tos_branches - Utils.valid_covered.keys())
def check_no_new_branches(objs): """ Checks if a list of 11 comparisons on different characters has no coverage event in between. If this happens the generator is stuck in a loop which is not able to proceed usefully. :param objs: """ seen_indexes = set() for obj in objs: if Utils.is_real_input_comparison(obj, Utils.max_index - 1): seen_indexes.add(tuple(obj["index"])) if len(seen_indexes) >= 10: return True else: seen_indexes = set() return False
def calc_stack(objs) -> List[str]: """ Returns the smallest stack in which a comparison with the last character was done :param objs: :return: """ robjs = reversed(objs) stack = [] ident = -1 for obj in robjs: real_input_comparison = Utils.is_real_input_comparison(obj, Utils.max_index - 1) if ident == -1 and real_input_comparison: ident = int(obj["index"][0]) if ident != -1 and real_input_comparison: if ident in obj["index"]: stack = stack if stack and len(stack) < len(obj["stack"]) else obj["stack"] else: return stack return stack