def run_cpr(program_path, patch_list): emitter.sub_title("Evaluating Patch Pool") values.CONF_TIME_CHECK = None satisfied = utilities.check_budget(values.DEFAULT_TIME_DURATION) if satisfied: emitter.warning("\t[warning] ending due to timeout of " + str(values.DEFAULT_TIME_DURATION) + " minutes") iteration = 0 assertion_template = values.SPECIFICATION_TXT binary_dir_path = "/".join(program_path.split("/")[:-1]) while not satisfied and len(patch_list) > 0: if iteration == 0: test_input_list = values.LIST_TEST_INPUT seed_id = 0 for argument_list in test_input_list: time_check = time.time() poc_path = None iteration = iteration + 1 seed_id = seed_id + 1 values.ITERATION_NO = iteration klee_out_dir = binary_dir_path + "/klee-out-" + str( test_input_list.index(argument_list)) argument_list = app.configuration.extract_input_arg_list( argument_list) generalized_arg_list = [] for arg in argument_list: if arg in (values.LIST_SEED_FILES + list(values.LIST_TEST_FILES.values())): poc_path = arg values.FILE_POC_SEED = arg values.FILE_POC_GEN = arg generalized_arg_list.append("$POC") else: generalized_arg_list.append(arg) emitter.sub_sub_title("Iteration: " + str(iteration) + " - Using Seed #" + str(seed_id)) emitter.highlight("\tUsing Arguments: " + str(generalized_arg_list)) emitter.highlight("\tUsing Input: " + str(poc_path)) values.ARGUMENT_LIST = generalized_arg_list _, second_var_list = generator.generate_angelic_val( klee_out_dir, generalized_arg_list, poc_path) exit_code = run_concolic_execution(program_path + ".bc", generalized_arg_list, second_var_list, True) # assert exit_code == 0 duration = (time.time() - time_check) / 60 generated_path_list = app.parallel.generate_symbolic_paths( values.LIST_PPC, generalized_arg_list, poc_path) if generated_path_list: values.LIST_GENERATED_PATH = generated_path_list + values.LIST_GENERATED_PATH values.LIST_PPC = [] values.TIME_TO_EXPLORE = values.TIME_TO_EXPLORE + duration # check if new path hits patch location / fault location gen_masked_byte_list = generator.generate_mask_bytes( klee_out_dir, poc_path) if values.FILE_POC_SEED not in values.MASK_BYTE_LIST: values.MASK_BYTE_LIST[ values.FILE_POC_SEED] = gen_masked_byte_list else: current_mask_list = values.MASK_BYTE_LIST[ values.FILE_POC_SEED] values.MASK_BYTE_LIST[values.FILE_POC_SEED] = sorted( list(set(current_mask_list + gen_masked_byte_list))) distance.update_distance_map() if not oracle.is_loc_in_trace(values.CONF_LOC_PATCH): continue if not values.SPECIFICATION_TXT and not oracle.is_loc_in_trace( values.CONF_LOC_BUG): continue time_check = time.time() assertion, count_obs = generator.generate_assertion( assertion_template, Path(binary_dir_path + "/klee-last/").resolve()) # print(assertion.serialize()) patch_list = reduce( patch_list, Path(binary_dir_path + "/klee-last/").resolve(), assertion) emitter.note( "\t\t|P|=" + str(utilities.count_concrete_patches(patch_list)) + ":" + str(len(patch_list))) duration = (time.time() - time_check) / 60 values.TIME_TO_REDUCE = values.TIME_TO_REDUCE + duration satisfied = utilities.check_budget( values.DEFAULT_TIME_DURATION) if satisfied: emitter.warning("\t[warning] ending due to timeout of " + str(values.DEFAULT_TIME_DURATION) + " minutes") break emitter.success( "\t\tend of concolic exploration using user-provided seeds") emitter.success("\t\t\t|P|=" + str(utilities.count_concrete_patches(patch_list)) + ":" + str(len(patch_list))) values.COUNT_TEMPLATE_END_SEED = len(patch_list) values.COUNT_PATCH_END_SEED = utilities.count_concrete_patches( patch_list) else: iteration = iteration + 1 values.ITERATION_NO = iteration emitter.sub_sub_title("Iteration: " + str(iteration)) time_check = time.time() argument_list = values.ARGUMENT_LIST second_var_list = values.SECOND_VAR_LIST # if oracle.is_loc_in_trace(values.CONF_LOC_PATCH): gen_arg_list, gen_var_list, patch_list, argument_list, poc_path = select_new_input( patch_list) if not patch_list: emitter.warning("\t\t[warning] unable to generate a patch") break elif not gen_arg_list and not gen_var_list: emitter.warning( "\t\t[warning] no more paths to generate new input") break assert gen_arg_list # there should be a concrete input # print(">> new input: " + str(gen_arg_list)) ## Concolic execution of concrete input and patch candidate to retrieve path constraint. exit_code = run_concolic_execution(program_path + ".bc", gen_arg_list, gen_var_list) # assert exit_code == 0 duration = (time.time() - time_check) / 60 values.TIME_TO_EXPLORE = values.TIME_TO_EXPLORE + duration # Checks for the current coverage. satisfied = utilities.check_budget(values.DEFAULT_TIME_DURATION) time_check = time.time() values.LIST_GENERATED_PATH = app.parallel.generate_symbolic_paths( values.LIST_PPC, argument_list, poc_path) values.LIST_PPC = [] # check if new path hits patch location / fault location if not oracle.is_loc_in_trace(values.CONF_LOC_PATCH): continue if not values.SPECIFICATION_TXT and not oracle.is_loc_in_trace( values.CONF_LOC_BUG): continue distance.update_distance_map() ## Reduces the set of patch candidates based on the current path constraint assertion, count_obs = generator.generate_assertion( assertion_template, Path(binary_dir_path + "/klee-last/").resolve()) # print(assertion.serialize()) patch_list = reduce( patch_list, Path(binary_dir_path + "/klee-last/").resolve(), assertion) emitter.note("\t\t|P|=" + str(utilities.count_concrete_patches(patch_list)) + ":" + str(len(patch_list))) duration = (time.time() - time_check) / 60 values.TIME_TO_REDUCE = values.TIME_TO_REDUCE + duration if satisfied: emitter.warning("\t[warning] ending due to timeout of " + str(values.DEFAULT_TIME_DURATION) + " minutes") if values.DEFAULT_COLLECT_STAT: ranked_patch_list = rank_patches(patch_list) update_rank_matrix(ranked_patch_list, iteration) definitions.FILE_PATCH_SET = definitions.DIRECTORY_OUTPUT + "/patch-set-ranked-" + str( iteration) writer.write_patch_set(ranked_patch_list, definitions.FILE_PATCH_SET) writer.write_as_json(values.LIST_PATCH_RANKING, definitions.FILE_PATCH_RANK_MATRIX) if not patch_list: values.COUNT_PATCH_END = len(patch_list) emitter.warning("\t\t[warning] unable to generate a patch") else: definitions.FILE_PATCH_SET = definitions.DIRECTORY_OUTPUT + "/patch-set-original" writer.write_patch_set(patch_list, definitions.FILE_PATCH_SET) ranked_patch_list = rank_patches(patch_list) print_patch_list(ranked_patch_list) definitions.FILE_PATCH_SET = definitions.DIRECTORY_OUTPUT + "/patch-set-ranked" writer.write_patch_set(ranked_patch_list, definitions.FILE_PATCH_SET) if values.DEFAULT_COLLECT_STAT: check_infeasible_paths(patch_list) if values.DEFAULT_PATCH_TYPE == values.OPTIONS_PATCH_TYPE[1]: values.COUNT_PATCH_END = utilities.count_concrete_patches( ranked_patch_list) values.COUNT_TEMPLATE_END = len(patch_list) else: values.COUNT_PATCH_END = len(ranked_patch_list)
def run_concolic_exploration(program_path, patch_list): values.CONF_TIME_CHECK = None satisfied = utilities.check_budget(values.DEFAULT_TIMEOUT_CEGIS_EXPLORE) iteration = 0 emitter.sub_title("Concolic Path Exploration") assertion_template = values.SPECIFICATION_TXT max_count = 0 largest_assertion = None largest_path_condition = None while not satisfied: if iteration == 0: second_var_list = list() seed_id = 0 test_input_list = values.LIST_TEST_INPUT for argument_list in test_input_list: poc_path = None iteration = iteration + 1 seed_id = seed_id + 1 values.ITERATION_NO = iteration emitter.sub_sub_title("Iteration: " + str(iteration)) output_dir_path = definitions.DIRECTORY_OUTPUT klee_out_dir = output_dir_path + "/klee-out-repair-" + str( iteration - 1) argument_list = app.configuration.extract_input_arg_list( argument_list) generalized_arg_list = [] for arg in argument_list: if arg in (list(values.LIST_SEED_FILES.values()) + list(values.LIST_TEST_FILES.values())): poc_path = arg values.FILE_POC_SEED = arg values.FILE_POC_GEN = arg generalized_arg_list.append("$POC") else: generalized_arg_list.append(arg) emitter.sub_sub_title("Iteration: " + str(iteration) + " - Using Seed #" + str(seed_id)) emitter.highlight("\tUsing Arguments: " + str(generalized_arg_list)) emitter.highlight("\tUsing Input File: " + str(poc_path)) if values.LIST_TEST_BINARY: program_path = values.LIST_TEST_BINARY[seed_id - 1] values.CONF_PATH_PROGRAM = program_path else: program_path = values.CONF_PATH_PROGRAM extractor.extract_byte_code(program_path) if not os.path.isfile(program_path + ".bc"): app.utilities.error_exit( "Unable to generate bytecode for " + program_path) values.ARGUMENT_LIST = generalized_arg_list _, second_var_list = generator.generate_angelic_val( klee_out_dir, generalized_arg_list, poc_path) exit_code = run_concolic_execution(program_path + ".bc", generalized_arg_list, second_var_list, True, klee_out_dir) # assert exit_code == 0 generated_path_list = app.parallel.generate_symbolic_paths( values.LIST_PPC, generalized_arg_list, poc_path, program_path) if generated_path_list: values.LIST_GENERATED_PATH = generated_path_list + values.LIST_GENERATED_PATH values.LIST_PPC = [] # klee_dir = Path(binary_dir_path + "/klee-last/").resolve() assertion, count_obs = generator.generate_assertion( assertion_template, klee_out_dir) if count_obs > max_count: max_count = count_obs largest_assertion = assertion path_constraint_file_path = str( klee_out_dir) + "/test000001.smt2" largest_path_condition = extractor.extract_formula_from_file( path_constraint_file_path) satisfied = utilities.check_budget( values.DEFAULT_TIMEOUT_CEGIS_EXPLORE) # check if new path hits patch location / fault location gen_masked_byte_list = generator.generate_mask_bytes( klee_out_dir, poc_path) if values.FILE_POC_SEED not in values.MASK_BYTE_LIST: values.MASK_BYTE_LIST[ values.FILE_POC_SEED] = gen_masked_byte_list else: current_mask_list = values.MASK_BYTE_LIST[ values.FILE_POC_SEED] values.MASK_BYTE_LIST[values.FILE_POC_SEED] = sorted( list(set(current_mask_list + gen_masked_byte_list))) distance.update_distance_map() if not oracle.is_loc_in_trace(values.CONF_LOC_PATCH): continue if not values.SPECIFICATION_TXT and not oracle.is_loc_in_trace( values.CONF_LOC_BUG): continue if satisfied: emitter.warning("\t[warning] ending due to timeout of " + str(values.DEFAULT_TIMEOUT_CEGIS_EXPLORE) + " minutes") else: iteration = iteration + 1 values.ITERATION_NO = iteration emitter.sub_sub_title("Iteration: " + str(iteration)) argument_list = values.ARGUMENT_LIST second_var_list = values.SECOND_VAR_LIST gen_arg_list, gen_var_list, patch_list, argument_list, poc_path, program_path = select_new_input( patch_list) output_dir_path = definitions.DIRECTORY_OUTPUT klee_out_dir = output_dir_path + "/klee-out-repair-" + str( iteration - 1) if not patch_list: emitter.warning("\t\t[warning] unable to generate a patch") break elif not gen_arg_list and not gen_var_list: emitter.warning( "\t\t[warning] no more paths to generate new input") break assert gen_arg_list # there should be a concrete input time_check = time.time() ## Concolic execution of concrete input and patch candidate to retrieve path constraint. exit_code = run_concolic_execution(program_path + ".bc", gen_arg_list, gen_var_list, False, klee_out_dir) duration = (time.time() - time_check) / 60 values.TIME_TO_EXPLORE = values.TIME_TO_EXPLORE + duration # assert exit_code == 0 # klee_dir = Path(binary_dir_path + "/klee-last/").resolve() assertion, count_obs = generator.generate_assertion( assertion_template, klee_out_dir) if count_obs > max_count: max_count = count_obs largest_assertion = assertion path_constraint_file_path = str( klee_out_dir) + "/test000001.smt2" largest_path_condition = extractor.extract_formula_from_file( path_constraint_file_path) # Checks for the current coverage. satisfied = utilities.check_budget( values.DEFAULT_TIMEOUT_CEGIS_EXPLORE) values.LIST_GENERATED_PATH = app.parallel.generate_symbolic_paths( values.LIST_PPC, argument_list, poc_path, program_path) values.LIST_PPC = [] # check if new path hits patch location / fault location if not oracle.is_loc_in_trace(values.CONF_LOC_PATCH): continue if not values.SPECIFICATION_TXT and not oracle.is_loc_in_trace( values.CONF_LOC_BUG): continue distance.update_distance_map() if satisfied: emitter.warning("\t[warning] ending due to timeout of " + str(values.DEFAULT_TIMEOUT_CEGIS_EXPLORE) + " minutes") return largest_assertion, largest_path_condition
def run_cegis(program_path, project_path, patch_list): test_output_list = values.LIST_TEST_OUTPUT test_template = reader.collect_specification(test_output_list[0]) binary_dir_path = "/".join(program_path.split("/")[:-1]) time_check = time.time() assertion, largest_path_condition = concolic.run_concolic_exploration( program_path, patch_list) duration = (time.time() - time_check) / 60 values.TIME_TO_EXPLORE = duration emitter.normal("\tcombining explored program paths") if not assertion: patch = patch_list[0] emitter.emit_patch(patch, message="\tfinal patch: ") return program_specification = generator.generate_program_specification( binary_dir_path) complete_specification = And(Not(assertion), program_specification) emitter.normal("\tcomputed the program specification formula") emitter.sub_title("Evaluating Patch Pool") iteration = 0 output_dir = definitions.DIRECTORY_OUTPUT counter_example_list = [] time_check = time.time() values.CONF_TIME_CHECK = None satisfied = utilities.check_budget(values.DEFAULT_TIMEOUT_CEGIS_REFINE) patch_generator = generator.generate_patch(project_path, counter_example_list) count_throw = 0 while not satisfied: iteration = iteration + 1 values.ITERATION_NO = iteration emitter.sub_sub_title("Iteration: " + str(iteration)) patch = next(patch_generator, None) if not patch: emitter.error("[error] cannot generate a patch") patch_formula = app.generator.generate_formula_from_patch(patch) emitter.emit_patch(patch, message="\tgenerated patch: ") patch_formula_extended = generator.generate_extended_patch_formula( patch_formula, largest_path_condition) violation_check = And(complete_specification, patch_formula_extended) if is_sat(violation_check): model = generator.generate_model(violation_check) # print(model) arg_list = values.ARGUMENT_LIST poc_path = values.CONF_PATH_POC values.FILE_POC_GEN = definitions.DIRECTORY_OUTPUT + "/violation-" + str( values.ITERATION_NO) gen_path = values.FILE_POC_GEN input_arg_list, input_var_list = generator.generate_new_input( violation_check, arg_list, poc_path, gen_path) klee_out_dir = output_dir + "/klee-output-" + str(iteration) klee_test_file = output_dir + "/klee-test-" + str(iteration) exit_code = concolic.run_concrete_execution( program_path + ".bc", input_arg_list, True, klee_out_dir) # assert exit_code == 0 emitter.normal("\t\tgenerating new assertion") test_assertion, count_obs = generator.generate_assertion( test_template, klee_out_dir) write_smtlib(test_assertion, klee_test_file) counter_example_list.append((klee_test_file, klee_out_dir)) emitter.highlight("\t\tnew counter-example added") patch = None emitter.highlight("\t\tremoving current patch") count_throw = count_throw + 1 else: klee_test_file = output_dir + "/klee-test-FINAL" # print(to_smtlib(violation_check, False)) write_smtlib(violation_check, klee_test_file) break satisfied = utilities.check_budget(values.DEFAULT_TIMEOUT_CEGIS_REFINE) if satisfied: emitter.warning("\t[warning] ending due to timeout of " + str(values.DEFAULT_TIMEOUT_CEGIS_REFINE) + " minutes") duration = (time.time() - time_check) / 60 values.TIME_TO_REDUCE = duration # patch_list = [patch] # definitions.FILE_PATCH_SET = definitions.DIRECTORY_OUTPUT + "/patch-set-cegis" # writer.write_patch_set(patch_list, definitions.FILE_PATCH_SET) # patch = next(patch_generator, None) # while patch is not None: # patch_formula = app.generator.generate_formula_from_patch(patch) # patch_formula_extended = generator.generate_extended_patch_formula(patch_formula, largest_path_condition) # violation_check = And(complete_specification, patch_formula_extended) # if is_unsat(violation_check): # count_final = count_final + 1 # patch = next(patch_generator, None) emitter.emit_patch(patch, message="\tfinal patch: ") values.COUNT_PATCH_END = values.COUNT_PATCH_START - count_throw