from ..surveyors import Slicecutor
from sleak import SleakMeta
from angr.errors import AngrExitError
from ..sliceinfo import SliceInfo
import logging

l = logging.getLogger("analysis.sleakslice")

class Sleakslice(SleakMeta):
    """
    Stack leak detection, slices through the program towards identified output
    functions.

    """

    def __init__(self, istate=None, targets=None, mode=None, argc=None):
        """
        @istate: an initial state to use
        @targets: a list of target addrs to look for
        @argc: how many symbolic arguments ?
        """

        self.prepare(istate=istate, targets=targets, mode=mode, argc=argc)
        self.slices = []
        self.failed_targets = [] # Targets outside the CFG
        #self.found_paths = []

        self.run()

    def run(self):

        self.cfg = self._p.analyses.CFG()
        self.ddg = self._p.analyses.DDG(self.cfg)
        self.cdg = self._p.analyses.CDG(cfg=self.cfg)

        for t in self.targets.values():
            l.debug("Running slice towards 0x%x" % t)
            #with self._resilience():
            try:
                r = self._run_slice(target_addr = t)
            except AngrExitError as error:  # not in the CFG
                self.failed_targets.append(t)
                l.debug(error)
                l.info("Skipping target 0x%x (%s)" % (t, self.target_name(t)))
                continue

            self.slices.append(r)
            self._check_found_paths()

    @property
    def terminated_paths(self):
        """
        Where did the analysis stop ?
        """
        paths=[]
        for sl in self.slices:
            paths = paths + sl.deadended + sl.cut
        return paths

    def _run_slice(self, target_addr, target_stmt = -1, begin = None):
        """
        @begin: where to start ? The default is the entry point of the program
        @target_addr: address of the destination's basic block
        @target_stmt: idx of the VEX statement in that block
        """
        target_irsb = self.cfg.get_any_irsb(target_addr)

        if target_irsb is None:
            raise AngrExitError("The CFG doesn't contain any IRSB starting at "
                                "0x%x" % target_addr)

        if begin is None:
            begin = self.ipath.addr

        bwslice = self._p.analyses.BackwardSlice(self.cfg, self.cfg, self.ddg,
                                                  target_irsb, target_stmt,
                                                  control_flow_slice=False)

        self.annocfg = bwslice.annotated_cfg(start_point=self.ipath.addr)
        slicecutor = Slicecutor(self._p, self.annocfg, start=self.ipath, targets=[target_addr])
        slicecutor.run()
        return slicecutor

    def _check_found_paths(self):
        """
        Iterates over all found paths to identify leaking ones
        """
        results = []
        if len(self.found_paths) > 0:
            self.reached_target = True

        # Found paths : output function reached
        for p in self.found_paths:
            r = self._check_path(p)
            if r is not None:
                results.append(r)
        self.leaks = results



@@ -98,42 +98,8 @@
 ror%0A
-from ..sliceinfo import SliceInfo%0A
 impo

Remove obsolete dependency