Example #1
0
def refine_for_under_approx(patch_formula, path_condition, patch_space, p_specification):
    parameter_constraint = smt2.generate_constraint_for_patch_space(patch_space)
    patch_space_constraint = patch_formula
    if parameter_constraint:
        patch_space_constraint = And(patch_formula, parameter_constraint)
    path_feasibility = And(path_condition, And(patch_space_constraint, p_specification))
    path_constraint = And(path_condition, patch_formula)
    if values.VALID_INPUT_SPACE:
        input_space_constraint = Not(smt2.generate_constraint_for_input_space(values.VALID_INPUT_SPACE))
        path_feasibility = And(path_condition, And(patch_space_constraint, input_space_constraint))
        path_constraint = And(And(path_condition, input_space_constraint), patch_formula)
    # invalid input range is used to check for violations

    refined_patch_space = patch_space
    is_under_approx = False
    if is_sat(path_feasibility):
        is_under_approx = True
        if values.DEFAULT_REFINE_METHOD in ["under-approx", "overfit"]:
            emitter.debug("refining for universal quantification")
            if parameter_constraint:
                refined_patch_space = refine_parameter_space(path_constraint, patch_space, p_specification)
                is_under_approx = False
            else:
                refined_patch_space = None
    return refined_patch_space, is_under_approx
Example #2
0
def check_patch_feasibility(assertion, var_relationship, patch_constraint, path_condition, index):  # TODO
    path_constraint = And(path_condition, patch_constraint)
    patch_score = 0
    is_under_approx = None
    is_over_approx = None
    result = True
    if assertion:
        if is_sat(path_constraint):
            if is_loc_in_trace(values.CONF_LOC_BUG):
                patch_score = 2
                is_under_approx = not is_unsat(And(path_constraint, Not(assertion)))
                if values.DEFAULT_REFINE_METHOD in ["under-approx", "overfit"]:
                    if is_under_approx:
                        emitter.debug("removing due to universal quantification")
                        result = False

                negated_path_condition = values.NEGATED_PPC_FORMULA
                path_constraint = And(negated_path_condition, patch_constraint)
                is_over_approx = not is_unsat(And(path_constraint, assertion))
                if values.DEFAULT_REFINE_METHOD in ["over-approx", "overfit"]:
                    if is_over_approx:
                        emitter.debug("removing due to existential quantification")
                        result = False
            else:
                patch_score = 1
            # else:
            #     specification = And(path_condition, Not(patch_constraint))
            #     existential_quantification = is_unsat(And(specification, assertion))
            #     result = existential_quantification

    return result, index, patch_score, is_under_approx, is_over_approx
Example #3
0
def initialize():
    emitter.title("Initializing Program")
    test_input_list = values.LIST_TEST_INPUT
    second_var_list = list()
    output_dir_path = definitions.DIRECTORY_OUTPUT
    emitter.sub_title("Running Test-Suite")
    test_case_id = 0
    count_seeds = len(values.LIST_SEED_INPUT)
    count_inputs = len(test_input_list)
    for argument_list in test_input_list[:count_inputs - count_seeds]:
        print_argument_list = app.configuration.extract_input_arg_list(
            argument_list)
        generalized_arg_list = []
        seed_file = None
        test_case_id = test_case_id + 1
        for arg in print_argument_list:
            if arg in (list(values.LIST_SEED_FILES.values()) +
                       list(values.LIST_TEST_FILES.values())):
                generalized_arg_list.append("$POC")
                seed_file = arg
            else:
                generalized_arg_list.append(arg)

        emitter.sub_sub_title("Test Case #" + str(test_case_id))
        emitter.highlight("\tUsing Arguments: " + str(generalized_arg_list))
        emitter.highlight("\tUsing Input File: " + str(seed_file))
        emitter.debug("input list in test case:" + argument_list)
        argument_list = app.configuration.extract_input_arg_list(argument_list)
        klee_out_dir = output_dir_path + "/klee-out-test-" + str(test_case_id -
                                                                 1)
        if values.LIST_TEST_BINARY:
            program_path = values.LIST_TEST_BINARY[test_case_id - 1]
            values.CONF_PATH_PROGRAM = program_path
        else:
            program_path = values.CONF_PATH_PROGRAM
        emitter.highlight("\tUsing Binary: " + str(program_path))
        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)

        exit_code = run_concrete_execution(program_path + ".bc", argument_list,
                                           True, klee_out_dir)
        assert exit_code == 0
        # set location of bug/crash
        values.IS_CRASH = False
        latest_crash_loc = reader.collect_crash_point(values.FILE_MESSAGE_LOG)
        # if oracle.is_loc_in_trace(values.CONF_LOC_PATCH):
        #     values.USEFUL_SEED_ID_LIST.append(test_case_id)
        if latest_crash_loc:
            values.IS_CRASH = True
            emitter.success("\t\t\t[info] identified a crash location: " +
                            str(latest_crash_loc))
            if latest_crash_loc not in values.CONF_LOC_LIST_CRASH:
                values.CONF_LOC_LIST_CRASH.append(latest_crash_loc)
Example #4
0
def run_concrete_execution(program,
                           argument_list,
                           print_output=False,
                           output_dir=None):
    """
    This function will execute the program in concrete mode using the concrete inputs
        program: the absolute path of the bitcode of the program
        argument_list : a list containing each argument in the order that should be fed to the program
        second_var_list: a list of tuples where a tuple is (var identifier, var size, var value)
    """
    logger.info("running concolic execution")
    emitter.normal("\texecuting klee in concrete mode")
    global File_Log_Path
    current_dir = os.getcwd()
    directory_path = "/".join(str(program).split("/")[:-1])
    emitter.debug("changing directory:" + directory_path)
    os.chdir(directory_path)
    binary_name = str(program).split("/")[-1]
    input_argument = ""
    runtime_lib_path = definitions.DIRECTORY_LIB + "/libtrident_runtime.bca"
    for argument in argument_list:
        if "$POC" in argument:
            argument = values.FILE_POC_GEN
        #     if "_" in argument:
        #         file_index = "_".join(str(argument).split("_")[1:])
        #         argument = values.LIST_TEST_FILES[file_index]
        #     else:
        #         argument = values.CONF_PATH_POC
        #         if values.FILE_POC_GEN:
        #             argument = values.FILE_POC_GEN
        input_argument += " " + str(argument)
    if output_dir:
        klee_command = "klee --output-dir=" + str(output_dir) + " "
    else:
        klee_command = "klee "
    klee_command += "--posix-runtime " \
                    "--libc=uclibc " \
                    "--search=dfs " \
                    "--write-smt2s " \
                    "--external-calls=all " \
                    "--max-forks {0} ".format(values.DEFAULT_MAX_FORK) \
                    + values.CONF_KLEE_FLAGS + " " \
                    + "--link-llvm-lib={0} ".format(runtime_lib_path) \
                    + "{0} ".format(binary_name) \
                    + input_argument
    if not print_output:
        klee_command += " > " + File_Log_Path + " 2>&1 "
    return_code = utilities.execute_command(klee_command)
    emitter.debug("changing directory:" + current_dir)
    os.chdir(current_dir)
    return return_code
Example #5
0
def recover_patch_list(result_list, patch_list, path_condition, assertion):
    recover_list = []
    emitter.error(
        "\t[error] something went wrong with patch validation, attempting to recover"
    )
    emitter.debug("result list size: " + str(len(result_list)))
    emitter.debug("patch list size: " + str(len(patch_list)))
    emitter.warning(
        "\t[warning] attempting to re-run parallel refinement: missing " +
        str(len(patch_list) - len(result_list)))

    diff_list_a = get_diff_list(result_list, patch_list)
    result_list_a = parallel.refine_patch_space(diff_list_a, path_condition,
                                                assertion)
    recover_list = update_index(result_list_a, diff_list_a, patch_list)
    if len(diff_list_a) != len(result_list_a):
        emitter.error(
            "\t[error] something went wrong with patch validation, attempting to recover"
        )
        emitter.debug("result list size: " + str(len(result_list)))
        emitter.debug("patch list size: " + str(len(patch_list)))
        emitter.warning(
            "\t[warning] attempting to re-run sequential refinement: missing "
            + str(len(diff_list_a) - len(result_list_a)))
        diff_list_b = get_diff_list(result_list_a, diff_list_a)
        result_list_b = parallel.refine_patch_space(diff_list_b,
                                                    path_condition, assertion,
                                                    True)
        recover_list = recover_list + update_index(result_list_b, diff_list_b,
                                                   patch_list)
    return recover_list
Example #6
0
def generate_flipped_path(ppc):
    """
    This function will check if a selected path is feasible
           ppc : partial path conditoin at chosen control loc
           chosen_control_loc: branch location selected for flip
           returns satisfiability of the negated path
    """
    parser = SmtLibParser()
    new_path = None
    try:
        script = parser.get_script(cStringIO(ppc))
        formula = script.get_last_formula()
        prefix = formula.arg(0)
        constraint = formula.arg(1)
        new_path = And(prefix, Not(constraint))
        assert str(new_path.serialize()) != str(formula.serialize())
    except Exception as ex:
        emitter.debug("Pysmt parser error, skipping path flip")
    finally:
        return new_path
Example #7
0
File: main.py Project: samithaj/CPR
def initialize():
    emitter.title("Initializing Program")
    program_path = values.CONF_PATH_PROGRAM
    extractor.extract_byte_code(program_path)
    test_input_list = values.LIST_TEST_INPUT
    second_var_list = list()
    directory_path = "/".join(str(program_path).split("/")[:-1])
    klee_out_dir = directory_path + "/klee-last"
    emitter.sub_title("Running Test-Suite")
    test_case_id = 0
    for argument_list in test_input_list:
        print_argument_list = app.configuration.extract_input_arg_list(argument_list)
        generalized_arg_list = []
        seed_file = None
        test_case_id = test_case_id + 1
        for arg in print_argument_list:
            if arg in (values.LIST_SEED_FILES + list(values.LIST_TEST_FILES.values())):
                generalized_arg_list.append("$POC")
                seed_file = arg
            else:
                generalized_arg_list.append(arg)

        emitter.sub_sub_title("Test Case #" + str(test_case_id))
        emitter.highlight("\tUsing Arguments: " + str(generalized_arg_list))
        emitter.highlight("\tUsing Input: " + str(seed_file))
        emitter.debug("input list in test case:" + argument_list)
        argument_list = app.configuration.extract_input_arg_list(argument_list)
        exit_code = run_concrete_execution(program_path + ".bc", argument_list, True)
        assert exit_code == 0
        # set location of bug/crash
        values.IS_CRASH = False
        latest_crash_loc = reader.collect_crash_point(values.FILE_MESSAGE_LOG)
        if latest_crash_loc:
            values.IS_CRASH = True
            emitter.success("\t\t\t[info] identified a crash location: " + str(latest_crash_loc))
            if latest_crash_loc not in values.CONF_LOC_LIST_CRASH:
                values.CONF_LOC_LIST_CRASH.append(latest_crash_loc)
Example #8
0
def run_concolic_execution(program,
                           argument_list,
                           second_var_list,
                           print_output=False,
                           klee_out_dir=None):
    """
    This function will execute the program in concolic mode using the generated ktest file
        program: the absolute path of the bitcode of the program
        argument_list : a list containing each argument in the order that should be fed to the program
        second_var_list: a list of tuples where a tuple is (var identifier, var size, var value)
    """
    logger.info("running concolic execution")

    global File_Log_Path
    current_dir = os.getcwd()
    directory_path = "/".join(str(program).split("/")[:-1])
    emitter.debug("changing directory:" + directory_path)
    project_path = values.CONF_DIR_SRC
    os.chdir(directory_path)
    binary_name = str(program).split("/")[-1]
    input_argument = ""
    # argument_list = str(argument_str).split(" ")
    for argument in argument_list:
        index = list(argument_list).index(argument)
        if "$POC" in argument:
            file_path = values.FILE_POC_GEN
            # if "_" in argument:
            #     file_index = "_".join(str(argument).split("_")[1:])
            #     file_path = values.LIST_TEST_FILES[file_index]
            # else:
            #     file_path = values.CONF_PATH_POC
            #     if values.FILE_POC_GEN:
            #         file_path = values.FILE_POC_GEN
            #     elif values.FILE_POC_SEED:
            #         file_path = values.FILE_POC_SEED
            concrete_file = open(file_path, 'rb')
            bit_size = os.fstat(concrete_file.fileno()).st_size
            input_argument += " A --sym-files 1 " + str(bit_size) + " "
        elif str(index) in values.CONF_MASK_ARG:
            input_argument += " " + argument
        else:
            input_argument += " --sym-arg " + str(len(str(argument)))
    ktest_path, return_code = generator.generate_ktest(argument_list,
                                                       second_var_list)
    ktest_log_file = "/tmp/ktest.log"
    ktest_command = "ktest-tool " + ktest_path + " > " + ktest_log_file
    utilities.execute_command(ktest_command)
    bit_length_list = reader.read_bit_length(ktest_log_file)
    if values.LIST_BIT_LENGTH:
        for var in bit_length_list:
            if var in values.LIST_BIT_LENGTH:
                if values.LIST_BIT_LENGTH[var] < bit_length_list[var]:
                    values.LIST_BIT_LENGTH[var] = bit_length_list[var]
            else:
                values.LIST_BIT_LENGTH[var] = bit_length_list[var]
    else:
        values.LIST_BIT_LENGTH = bit_length_list
    emitter.normal("\texecuting klee in concolic mode")
    # hit_location_flag = " "
    runtime_lib_path = definitions.DIRECTORY_LIB + "/libtrident_runtime.bca"
    # if values.CONF_DISTANCE_METRIC == "control-loc":
    hit_location_flag = "--hit-locations " + values.CONF_LOC_BUG + "," + values.CONF_LOC_PATCH
    if values.CONF_LOC_LIST_CRASH:
        crash_locations = ', '.join(
            ['{}'.format(loc) for loc in values.CONF_LOC_LIST_CRASH])
        hit_location_flag += "," + crash_locations + " "
    else:
        hit_location_flag += " "
    ppc_log_flag = ""
    if values.DEFAULT_DISTANCE_METRIC != values.OPTIONS_DIST_METRIC[2]:
        ppc_log_flag = "--log-ppc "

    klee_command = "timeout " + str(values.DEFAULT_TIMEOUT_KLEE_CONCOLIC) + " "
    if klee_out_dir:
        klee_command += "klee --output-dir=" + str(klee_out_dir) + " "
        values.KLEE_LAST_DIR = klee_out_dir
    else:
        klee_command += "klee "
    klee_command += "--posix-runtime " \
                    "--libc=uclibc " \
                    "--write-smt2s " \
                    "-allow-seed-extension " \
                    "-named-seed-matching " \
                    "--log-trace " \
                    + "--external-calls=all " \
                    + "--link-llvm-lib={0} " .format(runtime_lib_path) \
                    + "--max-time={0} ".format(values.DEFAULT_TIMEOUT_KLEE_CONCOLIC) \
                    + "{0}".format(ppc_log_flag) \
                    + "{0}".format(hit_location_flag) \
                    + "--max-forks {0} ".format(values.DEFAULT_MAX_FORK) \
                    + values.CONF_KLEE_FLAGS + " " \
                    + "--seed-out={0} ".format(ktest_path) \
                    + "{0} ".format(binary_name) \
                    + input_argument
    if not print_output:
        klee_command += " > " + File_Log_Path + " 2>&1 "
    return_code = utilities.execute_command(klee_command)
    emitter.debug("changing directory:" + current_dir)
    os.chdir(current_dir)

    # collect artifacts
    ppc_log_path = klee_out_dir + "/ppc.log"
    trace_log_path = klee_out_dir + "/trace.log"
    if values.DEFAULT_DISTANCE_METRIC != values.OPTIONS_DIST_METRIC[2]:
        ppc_list, path_formula = reader.collect_symbolic_path(
            ppc_log_path, project_path)
        values.LIST_PPC = values.LIST_PPC = ppc_list
        values.LAST_PPC_FORMULA = path_formula
        values.PREFIX_PPC_STR = reader.collect_symbolic_path_prefix(
            ppc_log_path, project_path)
    else:
        values.LAST_PPC_FORMULA = extractor.extract_largest_path_condition(
            klee_out_dir)
        if values.LAST_PPC_FORMULA:
            ppc_list = generator.generate_ppc_from_formula(
                values.LAST_PPC_FORMULA)
            values.LIST_PPC = values.LIST_PPC + ppc_list
        # else:
        #     values.LIST_PPC = []
    values.PREFIX_PPC_FORMULA = generator.generate_formula(
        values.PREFIX_PPC_STR)
    values.LIST_TRACE = reader.collect_trace(trace_log_path, project_path)
    if oracle.is_loc_in_trace(values.CONF_LOC_BUG) and oracle.is_loc_in_trace(
            values.CONF_LOC_PATCH):
        if values.DEFAULT_DISTANCE_METRIC != values.OPTIONS_DIST_METRIC[2]:
            values.NEGATED_PPC_FORMULA = generator.generate_path_for_negation()
        else:
            if values.LAST_PPC_FORMULA:
                values.NEGATED_PPC_FORMULA = generator.generate_negated_path(
                    values.LAST_PPC_FORMULA)
    else:
        values.NEGATED_PPC_FORMULA = None
    return return_code
Example #9
0
def generate_model(formula):
    """
           This function will invoke PySMT APIs to solve the provided formula and return the byte list of the model
           Arguments:
               formula: smtlib formatted formula
    """
    emitter.debug("extracting z3 model")
    model = get_model(formula)
    if model is None:
        return None
    path_script = "/tmp/z3_script_model"
    write_smtlib(formula, path_script)
    with open(path_script, "r") as script_file:
        script_lines = script_file.readlines()
    script = "".join(script_lines)
    var_list = set(re.findall("\(declare-fun (.+?) \(\)", script))
    sym_var_list = dict()
    for var_name in var_list:
        # sym_var_list[var_name] = dict()
        if "const_" in var_name and not "const_arr" in var_name:
            sym_def = Symbol(var_name, BV32)
            if sym_def not in model:
                continue
            x = model[sym_def]
            byte_list = dict()
            default_value = x.bv_signed_value()
            byte_list[0] = default_value
        else:
            sym_def = Symbol(var_name, ArrayType(BV32, BV8))
            if sym_def not in model:
                continue
            x = model[sym_def].simplify()
            byte_list = dict()
            value_array_map = x.array_value_assigned_values_map()
            default_value = int(str(x.array_value_default()).split("_")[0])
            if not value_array_map:
                byte_list[0] = default_value
            else:
                for idx, val in value_array_map.items():
                    index = int(str(idx).split("_")[0])
                    value = int(str(val).split("_")[0])
                    byte_list[index] = value

                max_index = max(list(byte_list.keys()))
                if var_name in values.LIST_BIT_LENGTH:
                    array_size = values.LIST_BIT_LENGTH[var_name] - 1
                    if var_name in ["A-data"]:
                        array_size = max_index

                else:
                    array_size = max_index + 1  # TODO: this could be wrong calculation

                if max_index == 0:
                    array_size = 2

                if var_name not in ["A-data"]:
                    for i in range(0, array_size):
                        if i not in byte_list:
                            byte_list[i] = default_value

                if var_name not in ["A-data", "A-data-stat"]:
                    for i in range(array_size - 1, -1, -1):
                        if byte_list[i] == 0:
                            byte_list.pop(i)
                        else:
                            break
        sym_var_list[var_name] = byte_list
    emitter.data("model var list", sym_var_list)
    return sym_var_list