from ..analysis import Analysis
from ..variableseekr import StackVariable

import simuvex

class CGC(Analysis):
    '''
    This analysis attempts to find memory corruption vulnerabilities in CGC stuff.
    '''

    @staticmethod
    def check_path(p):
        for e in p.exits():
            if e.reachable() and not e.is_unique() and len(e.split()) == 0:
                return True

            #for v in e.target.variables:
            #   if 'file' in v:
        st = p.last_initial_state
        for a in st.log.old_events:
            if isinstance(a, simuvex.SimActionData) and a.type == 'mem':
                addr = st.se.any_int(a.objects['addr'].ast)
                tb = (addr >> 24)
                if tb != 0xff and tb != 0xc and tb != 0x08:
                    return True

        print "Continuing"
        return False            #       return True

    def __init__(self):
        # make a CGC state
        s = self._p.initial_state()
        s.get_plugin('cgc')
        self.e = self._p.surveyors.Explorer(start=self._p.exit_to(self._p.entry, state=s), find=self.check_path)

        self.e.run()
        self.vuln_path = self.e.found[0]

        self.pov = """<?xml version="1.0" standalone="no" ?>
<!DOCTYPE pov SYSTEM "/usr/share/cgc-docs/replay.dtd">
<pov>
    <cbid>service</cbid>
        <replay>
"""

        s = self.vuln_path.last_initial_state
        for a in s.log.old_events:
            if isinstance(a, simuvex.SimActionData) and a.type == 'file' and s.se.solution(a.objects['fd'].ast, 1):
                max_size = s.se.max_int(a.objects['size'].ast)
                sval = s.se.any_str(a.objects['data'].ast)[:max_size]
                self.pov += "        <read><length>%d</length><match><data>%s</data></match></read>\n" % (max_size, repr(sval)[1:-1])

            elif isinstance(a, simuvex.SimActionData) and a.type == 'file' and s.se.solution(a.objects['fd'].ast, 0):
                max_size = s.se.max_int(a.objects['size'].ast)
                sval = s.se.any_str(a.objects['data'].ast)[:max_size]
                self.pov += "        <write>\n            <data>%s</data>\n        </write>\n" % repr(sval)[1:-1]

        self.pov += "</replay>\n</pov>\n"

@@ -241,14 +241,16 @@
 eck_
-path(p
+state(st
 ):%0A 
@@ -264,272 +264,107 @@
 for 
-e
+a
  in 
-p.exits():%0A            if e.reachable() and not e.is_unique() and len(e.split()) == 0:%0A                return True%0A%0A            #for v in e.target.variables:%0A            #   if 'file' in v:%0A        st = p.last_initial_state%0A        for a in st.log.old_events:
+reversed(st.log.old_events):%0A            if a.type == 'cgc_checkpoint':%0A                break%0A
 %0A   
@@ -632,26 +632,277 @@
     
-print %22Continuing%22
+st.log.add_event('cgc_checkpoint')%0A        st.log.old_events += st.log.new_events%0A        st.log.new_events = %5B %5D%0A        return False%0A%0A    @staticmethod%0A    def check_expr(expr):%0A        for v in expr.variables:%0A            if 'file' in v:%0A                return True%0A
 %0A   
@@ -922,38 +922,334 @@
 alse
+%0A%0A
     
-        #       return Tru
+def check_path(self, p):%0A        for e in p.exits():%0A            if not e.reachable():%0A                continue%0A%0A            if self.check_state(e.state):%0A                return True%0A%0A            if self.check_expr(e.target) and not e.is_unique() and len(e.split()) == 0:%0A                return True%0A%0A        return Fals
 e%0A%0A 

check memory accesses carefully