예제 #1
0
    def mutate(self) -> None:
        all_patches = self._mutate()

        if "patches" not in all_patches:
            logger.debug(f"No patches found by {self.NAME}")
            return

        for file in all_patches["patches"]:
            original_txt = self.slither.source_code[file].encode("utf8")
            patched_txt = original_txt
            offset = 0
            patches = all_patches["patches"][file]
            patches.sort(key=lambda x: x["start"])
            if not all(patches[i]["end"] <= patches[i + 1]["end"]
                       for i in range(len(patches) - 1)):
                logger.info(
                    f"Impossible to generate patch; patches collisions: {patches}"
                )
                continue
            for patch in patches:
                patched_txt, offset = apply_patch(patched_txt, patch, offset)
            diff = create_diff(self.slither, original_txt, patched_txt, file)
            if not diff:
                logger.info(f"Impossible to generate patch; empty {patches}")
            print(diff)
예제 #2
0
    def detect(self):
        all_results = self._detect()
        results = []
        # only keep valid result, and remove dupplicate
        [
            results.append(r) for r in all_results
            if self.slither.valid_result(r) and r not in results
        ]
        if results:
            if self.logger:
                info = '\n'
                for idx, result in enumerate(results):
                    if self.slither.triage_mode:
                        info += '{}: '.format(idx)
                    info += result['description']
                info += 'Reference: {}'.format(self.WIKI)
                self._log(info)
        if self.slither.generate_patches:
            for result in results:
                try:
                    self._format(self.slither, result)
                    if not 'patches' in result:
                        continue
                    result['patches_diff'] = dict()
                    for file in result['patches']:
                        original_txt = self.slither.source_code[file].encode(
                            'utf8')
                        patched_txt = original_txt
                        offset = 0
                        patches = result['patches'][file]
                        patches.sort(key=lambda x: x['start'])
                        if not all(patches[i]['end'] <= patches[i + 1]['end']
                                   for i in range(len(patches) - 1)):
                            self._log(
                                f'Impossible to generate patch; patches collisions: {patches}'
                            )
                            continue
                        for patch in patches:
                            patched_txt, offset = apply_patch(
                                patched_txt, patch, offset)
                        diff = create_diff(self.slither, original_txt,
                                           patched_txt, file)
                        if not diff:
                            self._log(
                                f'Impossible to generate patch; empty {result}'
                            )
                        else:
                            result['patches_diff'][file] = diff

                except FormatImpossible as e:
                    self._log(
                        f'\nImpossible to patch:\n\t{result["description"]}\t{e}'
                    )

        if results and self.slither.triage_mode:
            while True:
                indexes = input(
                    'Results to hide during next runs: "0,1,..." or "All" (enter to not hide results): '
                    .format(len(results)))
                if indexes == 'All':
                    self.slither.save_results_to_hide(results)
                    return []
                if indexes == '':
                    return results
                if indexes.startswith('['):
                    indexes = indexes[1:]
                if indexes.endswith(']'):
                    indexes = indexes[:-1]
                try:
                    indexes = [int(i) for i in indexes.split(',')]
                    self.slither.save_results_to_hide([
                        r for (idx, r) in enumerate(results) if idx in indexes
                    ])
                    return [
                        r for (idx, r) in enumerate(results)
                        if idx not in indexes
                    ]
                except ValueError:
                    self.logger.error(
                        yellow(
                            'Malformed input. Example of valid input: 0,1,2,3')
                    )
        return results
예제 #3
0
    def detect(self):
        all_results = self._detect()
        # Keep only dictionaries
        all_results = [r.data for r in all_results]
        results = []
        # only keep valid result, and remove dupplicate
        # pylint: disable=expression-not-assigned
        [
            results.append(r) for r in all_results
            if self.slither.valid_result(r) and r not in results
        ]
        if results:
            if self.logger:
                info = "\n"
                for idx, result in enumerate(results):
                    if self.slither.triage_mode:
                        info += "{}: ".format(idx)
                    info += result["description"]
                info += "Reference: {}".format(self.WIKI)
                self._log(info)
        if self.slither.generate_patches:
            for result in results:
                try:
                    self._format(self.slither, result)
                    if not "patches" in result:
                        continue
                    result["patches_diff"] = dict()
                    for file in result["patches"]:
                        original_txt = self.slither.source_code[file].encode(
                            "utf8")
                        patched_txt = original_txt
                        offset = 0
                        patches = result["patches"][file]
                        patches.sort(key=lambda x: x["start"])
                        if not all(patches[i]["end"] <= patches[i + 1]["end"]
                                   for i in range(len(patches) - 1)):
                            self._log(
                                f"Impossible to generate patch; patches collisions: {patches}"
                            )
                            continue
                        for patch in patches:
                            patched_txt, offset = apply_patch(
                                patched_txt, patch, offset)
                        diff = create_diff(self.slither, original_txt,
                                           patched_txt, file)
                        if not diff:
                            self._log(
                                f"Impossible to generate patch; empty {result}"
                            )
                        else:
                            result["patches_diff"][file] = diff

                except FormatImpossible as exception:
                    self._log(
                        f'\nImpossible to patch:\n\t{result["description"]}\t{exception}'
                    )

        if results and self.slither.triage_mode:
            while True:
                indexes = input(
                    'Results to hide during next runs: "0,1,...,{}" or "All" (enter to not hide results): '
                    .format(len(results)))
                if indexes == "All":
                    self.slither.save_results_to_hide(results)
                    return []
                if indexes == "":
                    return results
                if indexes.startswith("["):
                    indexes = indexes[1:]
                if indexes.endswith("]"):
                    indexes = indexes[:-1]
                try:
                    indexes = [int(i) for i in indexes.split(",")]
                    self.slither.save_results_to_hide([
                        r for (idx, r) in enumerate(results) if idx in indexes
                    ])
                    return [
                        r for (idx, r) in enumerate(results)
                        if idx not in indexes
                    ]
                except ValueError:
                    self.logger.error(
                        yellow(
                            "Malformed input. Example of valid input: 0,1,2,3")
                    )
        return results
예제 #4
0
    def detect(self) -> List[Dict]:
        results: List[Dict] = []
        # only keep valid result, and remove dupplicate
        # Keep only dictionaries
        for r in [output.data for output in self._detect()]:
            if self.compilation_unit.core.valid_result(r) and r not in results:
                results.append(r)
        if results and self.logger:
            self._log_result(results)
        if self.compilation_unit.core.generate_patches:
            for result in results:
                try:
                    self._format(self.compilation_unit, result)
                    if not "patches" in result:
                        continue
                    result["patches_diff"] = {}
                    for file in result["patches"]:
                        original_txt = self.compilation_unit.core.source_code[
                            file].encode("utf8")
                        patched_txt = original_txt
                        offset = 0
                        patches = result["patches"][file]
                        patches.sort(key=lambda x: x["start"])
                        if not all(patches[i]["end"] <= patches[i + 1]["end"]
                                   for i in range(len(patches) - 1)):
                            self._log(
                                f"Impossible to generate patch; patches collisions: {patches}"
                            )
                            continue
                        for patch in patches:
                            patched_txt, offset = apply_patch(
                                patched_txt, patch, offset)
                        diff = create_diff(self.compilation_unit, original_txt,
                                           patched_txt, file)
                        if not diff:
                            self._log(
                                f"Impossible to generate patch; empty {result}"
                            )
                        else:
                            result["patches_diff"][file] = diff

                except FormatImpossible as exception:
                    self._log(
                        f'\nImpossible to patch:\n\t{result["description"]}\t{exception}'
                    )

        if results and self.slither.triage_mode:
            while True:
                indexes = input(
                    f'Results to hide during next runs: "0,1,...,{len(results)}" or "All" (enter to not hide results): '
                )
                if indexes == "All":
                    self.slither.save_results_to_hide(results)
                    return []
                if indexes == "":
                    return results
                if indexes.startswith("["):
                    indexes = indexes[1:]
                if indexes.endswith("]"):
                    indexes = indexes[:-1]
                try:
                    indexes_converted = [int(i) for i in indexes.split(",")]
                    self.slither.save_results_to_hide([
                        r for (idx, r) in enumerate(results)
                        if idx in indexes_converted
                    ])
                    return [
                        r for (idx, r) in enumerate(results)
                        if idx not in indexes_converted
                    ]
                except ValueError:
                    self.logger.error(
                        yellow(
                            "Malformed input. Example of valid input: 0,1,2,3")
                    )
        results = sorted(results, key=lambda x: x["id"])

        return results