コード例 #1
0
        def f(self):
            patch_file = parse.PatchFile(test_filename)
            patch_file.getPatch()

            # There should only be one hunk in this file.
            self.assertEqual(len(patch_file.patches), 1)

            for hunk in patch_file.patches:
                result = context.context_changes(hunk)

                testcase = self.id().split('.')[-1]

                if testcase in self.errors:
                    expected = self.errors[testcase]
                else:
                    expected = {
                        'message': r'This patch can be applied\.',
                        'canApply': False
                    }

                self.assertRegex(result.messages, expected['message'])

                filename = os.path.join(os.getcwd(), hunk.getFileName())
                self.assertTrue(os.path.isfile(filename), filename)
                result = hunk.canApply()
                self.assertEqual(result, expected['canApply'], hunk)
コード例 #2
0
    def test_patch_CVE_2013_7348(self):
        patch_file = parse.PatchFile(
            "../vulnerableforks/patches/CVE-2013-7348.patch")
        patch_file.getPatch()

        result = context.context_changes(patch_file.patches[0])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)
コード例 #3
0
    def test_patch_CVE_2014_8481(self):
        patch_file = parse.PatchFile(
            "../vulnerableforks/patches/CVE-2014-8481.patch")
        patch_file.getPatch()

        # Look into why it fails!
        result = context.context_changes(patch_file.patches[0])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)
コード例 #4
0
    def test_name_change(self):
        patch_file = parse.PatchFile("patches/name-change.patch")
        patch_file.getPatch()

        # There should only be one hunk in this file.
        self.assertEqual(len(patch_file.patches), 1)

        for hunk in patch_file.patches:
            result = context.context_changes(hunk)
            self.assertRegex(result.messages, r'^The file .* does not exist$')
コード例 #5
0
        def f(self):
            patch_file = parse.PatchFile(test_filename)
            patch_file.getPatch()

            testcase = self.id().split('.')[-1]
            if testcase in self.errors:
                expected = self.errors[testcase]
            else:
                expected = {'result': '^$', 'success': True}

            patch_file.runPatch(dry_run=True)
            self.assertEqual(patch_file.runSuccess, expected['success'])
            self.assertRegex(patch_file.runResult, expected['result'])
コード例 #6
0
    def test_patch_CVE_2014_8172(self):
        patch_file = parse.PatchFile(
            "../vulnerableforks/patches/CVE-2014-8172.patch")
        patch_file.getPatch()

        result = context.context_changes(patch_file.patches[0])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[1])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[2])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[3])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[4])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[5])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[6])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[7])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[8])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[9])
        # print(result.messages)
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[10])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)
コード例 #7
0
        def f(self):
            patch_file = parse.PatchFile(test_filename)
            patch_file.getPatch()

            # There should only be one hunk in this file.
            self.assertEqual(len(patch_file.patches), 1)

            for hunk in patch_file.patches:
                result = context.context_changes(hunk)
                self.assertEqual(result.messages,
                                 "No context related issues found.")

            for hunk in patch_file.patches:
                filename = os.path.join(os.getcwd(), hunk.getFileName())
                self.assertTrue(os.path.isfile(filename), filename)
                result = hunk.canApply()
                self.assertTrue(result, hunk)
コード例 #8
0
    def test_patch_CVE_2014_9710(self):
        patch_file = parse.PatchFile(
            "../vulnerableforks/patches/CVE-2014-9710.patch")
        patch_file.getPatch()

        # Subpatch has been applied - look into why it fails!
        result = context.context_changes(patch_file.patches[0])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[1])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[2])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[3])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[4])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[5])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[6])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[7])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)
コード例 #9
0
    def test_patch_CVE_2012_2390(self):
        patch_file = parse.PatchFile(
            "../vulnerableforks/patches/CVE-2012-2390.patch")
        patch_file.getPatch()

        result = context.context_changes(patch_file.patches[0])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[1])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[2])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[3])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[4])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)
コード例 #10
0
def apply(pathToPatch, **kwargs):
    patch_file = parse.PatchFile(pathToPatch)
    patch_file.runPatch(reverse=kwargs['reverse'], dry_run=kwargs['dry_run'])
    if patch_file.runSuccess == True:
        print("Successfully applied")
        return 0
    else:  # Git apply failed to apply
        error_message = patch_file.runResult
        if kwargs['verbose'] > 0:
            print("Patch failed while it was run with git apply with error:")
            print(error_message)
        else:
            print("Patch failed to apply with git apply.")

        error_message_lines = error_message.split("\n")
        already_exists = set()
        file_not_found = set()
        does_not_apply = set()

        for line in error_message_lines:
            print(line)
            split_line = [s.strip() for s in line.split(":")]
            if line[0:2] == "  ":
                pass
            elif split_line[0] == "error":
                if split_line[1].startswith("corrupt patch"):
                    line_num = re.findall(r'\d+', split_line[1])
                    print(
                        "The patch is corrupted at line %s, stop processing..."
                        % line_num[0])
                    return 1

                if split_line[2] == "patch does not apply":
                    does_not_apply.add(split_line[1])
                elif split_line[2] == "already exists":
                    already_exists.add(split_line[1])
                elif split_line[2] == "No such file or directory":
                    file_not_found.add(split_line[1])
                elif split_line[2] == 'skipped':
                    # GIT does not translate the file name in this case.
                    filename = os.path.join(findGitPrefix(split_line[1]),
                                            split_line[1])
                    does_not_apply.add(filename)

        patch_file.getPatch()

        # TODO: Handle file that already exists

        # Handling sub patches do not apply
        # try_all_subpatches_input = input("Would you like to try and apply all subpatches? [Y/n] ")
        try_all_subpatches = True
        successful_subpatches = []
        already_applied_subpatches = []
        failed_subpatches_with_matched_code = []
        subpatches_without_matched_code = []
        no_match_patches = []
        applied_by_git_apply = []
        # not_tried_subpatches = []
        if not kwargs['dry_run']:
            see_patches = input(
                "We have found {} subpatches in the patch file. Would you like to see them? [Y/n] "
                .format(len(patch_file.patches)))
            see_patches = see_patches.upper() == "Y"
        else:
            see_patches = False

        for patch in patch_file.patches:
            fileName = patch.getFileName()

            # GIT has the behaviour where it prepends elements to the
            # path in order to get up to the root of the GIT
            # repository.  This means that the output of git apply is
            # not going to have the same file names as the patch file
            # itself.  We need to fix up the name we pulled from the
            # file so it matches the name returned by GIT.
            gitFileName = os.path.join(findGitPrefix(fileName), fileName)

            if see_patches:
                print("\n" + ":".join([fileName, str(patch._lineschanged[0])]))
                print(patch)

            subpatch_name = ":".join([fileName, str(patch._lineschanged[0])])

            if gitFileName in file_not_found:
                correct_loc = check_exist.checkFileExistsElsewhere(patch)
                if correct_loc != None:
                    does_not_apply.add(correct_loc)
                    file_not_found.remove(fileName)
                    fileName = correct_loc
                    patch._fileName = "/" + correct_loc
            elif gitFileName in does_not_apply:
                # [1:] is used to remove the leading slash

                # skip_current_patch = True
                # if not try_all_subpatches:
                #     print("\nFailed Subpatch : {}\n".format(subpatch_name))

                #     print(patch)
                #     skip_current_patch = (input("\nWould you like to try apply this subpatch? [Y/n] ").upper() != "Y")

                # if not try_all_subpatches and skip_current_patch:
                #     not_tried_subpatches.append(subpatch_name)
                #     continue

                # Try applying the subpatch as normal
                subpatch_run_status = patch.canApply(fileName)

                if subpatch_run_status == precheckStatus.CAN_APPLY:
                    successful_subpatches.append([patch, subpatch_name])
                elif subpatch_run_status == precheckStatus.ALREADY_APPLIED:
                    already_applied_subpatches.append(subpatch_name)
                else:
                    context_change_obj = cc.context_changes(patch)
                    diff_obj = context_change_obj.diff_obj
                    context_decision = context_change_obj.status
                    context_decision_msg = context_change_obj.messages

                    if diff_obj and diff_obj.match_status == MatchStatus.MATCH_FOUND:
                        match_found_helper(
                            patch,
                            diff_obj,
                            already_applied_subpatches,
                            failed_subpatches_with_matched_code,
                            subpatch_name,
                            context_decision,
                            fileName,
                            successful_subpatches,
                            context_decision_msg,
                        )

                    else:
                        subpatches_without_matched_code.append(subpatch_name)
                        no_match_patches.append(patch)
            elif gitFileName not in already_exists:
                applied_by_git_apply.append(subpatch_name)

        if len(successful_subpatches) > 0:
            print("-" * 70)
            print("{} subpatches can be applied successfully:\n".format(
                len(successful_subpatches)))
            if not kwargs['dry_run']:
                start_apply = input(
                    "Would you like to see these patches and try applying them? [Y/n] "
                )
                start_apply = start_apply.upper() == "Y"
            else:
                start_apply = True

            if start_apply:
                for patch in successful_subpatches:
                    if kwargs['verbose'] >= 1:
                        print()
                        print(patch[1])
                        print(patch[0])

                    if not kwargs['dry_run']:
                        apply_subpatch_input = input(
                            "The above subpatch can be applied successfully. Would you like to apply? [Y/n] "
                        )
                        apply_subpatch_input = apply_subpatch_input.upper(
                        ) == "Y"
                    else:
                        apply_subpatch_input = True

                    success = False
                    if apply_subpatch_input:
                        fileName = patch[0]._fileName
                        patchObj = patch[0]
                        success = patchObj.Apply(fileName,
                                                 dry_run=kwargs['dry_run'])
                    if success:
                        if kwargs['dry_run']:
                            print(
                                "%s would have been successfully applied (dry run)."
                                % patch[1])
                        else:
                            print("%s successfully applied!" % patch[1])
                    else:
                        print("%s Ignored" % patch[1])

        if len(failed_subpatches_with_matched_code) > 0:
            # failed_subpatches_with_matched_code.sort()
            print('\n' + '-' * 70)
            print(
                "Subpatches that we can't automatically apply, but think we have found where the patch should be applied:\n"
            )

            for (percentages, sp_name, line_number, context_decision_msg,
                 patch) in failed_subpatches_with_matched_code:
                add_percent, removed_percent, context_percent = percentages
                print("{} - Line Number: {}".format(sp_name, line_number))
                if kwargs['verbose'] >= 2:
                    print(patch)
                print(
                    "  Percentage of Added Lines Applied:   {:>6.2f}%".format(
                        add_percent))
                print(
                    "  Percentage of Removed Lines Applied: {:>6.2f}%".format(
                        removed_percent))
                print(
                    "  Percentage of Context Lines Found:   {:>6.2f}%".format(
                        context_percent))
                print(
                    f"  Context related reason for not applying the patch: {context_decision_msg}"
                )

            print(
                "\nNote that if all added lines are added and removed lines are removed, that means that the context may have changed in ways that affect the code"
            )

        if len(applied_by_git_apply) > 0:
            print("\n" + "-" * 70)
            print("Subpatches that were applied by git apply:")
            print("\n".join(applied_by_git_apply))

        if len(already_applied_subpatches) > 0:
            print("\n" + "-" * 70)
            print("Subpatches that were already applied:")
            print("\n".join(already_applied_subpatches))

        if len(subpatches_without_matched_code) > 0:
            print("\n" + "-" * 70)
            print(
                "Subpatches that did not apply, and we could not find where the patch should be applied:"
            )
            print("\n".join(subpatches_without_matched_code))

        if len(file_not_found) > 0:
            print("\n" + '-' * 70)
            print("The following files could not be found:")
            print("\n".join(file_not_found))

        # if len(not_tried_subpatches) > 0:
        #     print("\nSubpatches that we did not try and apply:")
        #     print("\n".join(not_tried_subpatches))

        return 1
コード例 #11
0
    def test_two_changes(self):
        patch_file = parse.PatchFile("patches/clean/two-changes.patch")
        patch_file.getPatch()

        # There should only be one hunk in this file.
        self.assertEqual(len(patch_file.patches), 2)
コード例 #12
0
 def test_no_patch(self):
     patch_file = parse.PatchFile("patches/does-not-exist.patch")
     self.assertRaises(FileNotFoundError, patch_file.getPatch)
コード例 #13
0
    def test_patch_CVE_2014_9644(self):
        patch_file = parse.PatchFile(
            "../vulnerableforks/patches/CVE-2014-9644.patch")
        patch_file.getPatch()

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[0])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[1])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[2])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[3])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[4])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[5])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[5])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[6])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[7])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[8])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[9])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[10])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[11])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[12])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[13])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[14])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[15])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[16])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # This file has been deleted.
        # result = context.context_changes(patch_file.patches[17])
        # self.assertTrue(result.status)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[18])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[19])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[20])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[21])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[22])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[23])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)
コード例 #14
0
    def test_patch_CVE_2013_7281(self):
        patch_file = parse.PatchFile(
            "../vulnerableforks/patches/CVE-2013-7281.patch")
        patch_file.getPatch()

        # Patch has already been applied
        result = context.context_changes(patch_file.patches[0])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # No context changes
        result = context.context_changes(patch_file.patches[1])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # No context changes
        result = context.context_changes(patch_file.patches[2])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Context has changed a little
        result = context.context_changes(patch_file.patches[3])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Context has changed a little
        result = context.context_changes(patch_file.patches[4])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[5])
        self.assertFalse(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[6])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[7])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[8])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        # Subpatch has been applied
        result = context.context_changes(patch_file.patches[9])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[10])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[11])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[12])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[13])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[14])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[15])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)

        result = context.context_changes(patch_file.patches[16])
        self.assertTrue(result.status)
        self.assertFalse(result.is_comment)