<commit_before>import os
import time
import angr
import signal
import socket
import claripy
import simuvex
import tempfile
import topsecret
import subprocess
import shellphish_qemu
from .tracerpov import TracerPoV
from .cachemanager import LocalCacheManager
from .simprocedures import receive
from .simprocedures import FixedOutTransmit, FixedInReceive, FixedRandom
from simuvex import s_options as so

import logging

l = logging.getLogger("tracer.Tracer")

# global writable attribute used for specifying cache procedures
GlobalCacheManager = None

class TracerInstallError(Exception):
    pass


class TracerEnvironmentError(Exception):
    pass


class TracerMisfollowError(Exception):
    pass


class TracerDynamicTraceOOBError(Exception):
    pass


class Tracer(object):
    '''
    Trace an angr path with a concrete input
    '''

    def __init__(self, binary, input=None, pov_file=None, simprocedures=None,
                 hooks=None, seed=None, preconstrain_input=True,
                 preconstrain_flag=True, resiliency=True, chroot=None,
                 add_options=None, remove_options=None):
        """
        :param binary: path to the binary to be traced
        :param input: concrete input string to feed to binary
        :param povfile: CGC PoV describing the input to trace
        :param hooks: A dictionary of hooks to add
        :param simprocedures: dictionary of replacement simprocedures
        :param seed: optional seed used for randomness, will be passed to QEMU
        :param preconstrain_input: should the path be preconstrained to the
            provided input
        :param preconstrain_flag: should the path have the cgc flag page
            preconstrained
        :param resiliency: should we continue to step forward even if qemu and
            angr disagree?
        :param chroot: trace the program as though it were executing in a
            chroot
        :param add_options: add options to the state which used to do tracing
        :param remove_options: remove options from the state which is used to
            do tracing
        """

        self.binary = binary
        self.input = input
        self.pov_file = pov_file
        self.preconstrain_input = preconstrain_input
        self.preconstrain_flag = preconstrain_flag
        self.simprocedures = {} if simprocedures is None else simprocedures
        self._hooks = {} if hooks is None else hooks

        for h in self._hooks:
            l.debug("Hooking %#x -> %s", h, self._hooks[h].__name__)

        if isinstance(seed, (int, long)):
            seed = str(seed)
        self.seed = seed
        self.resiliency = resiliency
        self.chroot = chroot
        self.add_options = set() if add_options is None else add_options
        self.constrained_addrs = []

        cm = LocalCacheManager() if GlobalCacheManager is None else GlobalCacheManager
        # cache managers need the tracer to be set for them
        self._cache_manager = cm
        self._cache_manager.set_tracer(self)

        # set by a cache manager
        self._loaded_from_cache = False

        if remove_options is None:
            self.remove_options = set()
        else:
            self.remove_options = remove_options

        if self.pov_file is None and self.input is None:
            raise ValueError("must specify input or pov_file")

        if self.pov_file is not None and self.input is not None:
            raise ValueError("cannot specify both a pov_file and an input")

        # validate seed
        if self.seed is not None:
            try:
                iseed = int(self.seed)
                if iseed > 4294967295 or iseed < 0:
                    raise ValueError
            except ValueError:
                raise ValueError(
                    "the passed seed is either not an integer or is not between 0 and UINT_MAX"
                    )

        # set up cache hook
        receive.cache_hook = self._cache_manager.cacher

        # a PoV was provided
        if self.pov_file is not None:
            self.pov_file = TracerPoV(self.pov_file)
            self.pov = True
        else:
            self.pov = False

        # internal project object, useful for obtaining certain kinds of info
        self._p = angr.Project(self.binary)

        self.base = None
        self.tracer_qemu = None
        self.tracer_qemu_path = None
        self._setup()

        l.debug("accumulating basic block trace...")
        l.debug("self.tracer_qemu_path: %s", self.tracer_qemu_path)

        # does the input cause a crash?
        self.crash_mode = False
        # if the input causes a crash, what address does it crash at?
        self.crash_addr = None

        # CGC flag data
        self.cgc_flag_bytes = [claripy.BVS("cgc-flag-byte-%d" % i, 8) for i in xrange(0x1000)]

        # content of the magic flag page as reported by QEMU
        # we need this to keep symbolic traces following the same path
        # as their dynamic counterpart
        self._magic_content = None

        # will set crash_mode correctly
        self.trace = self.dynamic_trace()

        l.debug("trace consists of %d basic blocks", len(self.trace))

        self.preconstraints = []

        # map of variable string names to preconstraints, for re-applying<commit_msg>Number of basic blocks is now INFO level log<commit_after>import os
import time
import angr
import signal
import socket
import claripy
import simuvex
import tempfile
import topsecret
import subprocess
import shellphish_qemu
from .tracerpov import TracerPoV
from .cachemanager import LocalCacheManager
from .simprocedures import receive
from .simprocedures import FixedOutTransmit, FixedInReceive, FixedRandom
from simuvex import s_options as so

import logging

l = logging.getLogger("tracer.Tracer")

# global writable attribute used for specifying cache procedures
GlobalCacheManager = None

class TracerInstallError(Exception):
    pass


class TracerEnvironmentError(Exception):
    pass


class TracerMisfollowError(Exception):
    pass


class TracerDynamicTraceOOBError(Exception):
    pass


class Tracer(object):
    '''
    Trace an angr path with a concrete input
    '''

    def __init__(self, binary, input=None, pov_file=None, simprocedures=None,
                 hooks=None, seed=None, preconstrain_input=True,
                 preconstrain_flag=True, resiliency=True, chroot=None,
                 add_options=None, remove_options=None):
        """
        :param binary: path to the binary to be traced
        :param input: concrete input string to feed to binary
        :param povfile: CGC PoV describing the input to trace
        :param hooks: A dictionary of hooks to add
        :param simprocedures: dictionary of replacement simprocedures
        :param seed: optional seed used for randomness, will be passed to QEMU
        :param preconstrain_input: should the path be preconstrained to the
            provided input
        :param preconstrain_flag: should the path have the cgc flag page
            preconstrained
        :param resiliency: should we continue to step forward even if qemu and
            angr disagree?
        :param chroot: trace the program as though it were executing in a
            chroot
        :param add_options: add options to the state which used to do tracing
        :param remove_options: remove options from the state which is used to
            do tracing
        """

        self.binary = binary
        self.input = input
        self.pov_file = pov_file
        self.preconstrain_input = preconstrain_input
        self.preconstrain_flag = preconstrain_flag
        self.simprocedures = {} if simprocedures is None else simprocedures
        self._hooks = {} if hooks is None else hooks

        for h in self._hooks:
            l.debug("Hooking %#x -> %s", h, self._hooks[h].__name__)

        if isinstance(seed, (int, long)):
            seed = str(seed)
        self.seed = seed
        self.resiliency = resiliency
        self.chroot = chroot
        self.add_options = set() if add_options is None else add_options
        self.constrained_addrs = []

        cm = LocalCacheManager() if GlobalCacheManager is None else GlobalCacheManager
        # cache managers need the tracer to be set for them
        self._cache_manager = cm
        self._cache_manager.set_tracer(self)

        # set by a cache manager
        self._loaded_from_cache = False

        if remove_options is None:
            self.remove_options = set()
        else:
            self.remove_options = remove_options

        if self.pov_file is None and self.input is None:
            raise ValueError("must specify input or pov_file")

        if self.pov_file is not None and self.input is not None:
            raise ValueError("cannot specify both a pov_file and an input")

        # validate seed
        if self.seed is not None:
            try:
                iseed = int(self.seed)
                if iseed > 4294967295 or iseed < 0:
                    raise ValueError
            except ValueError:
                raise ValueError(
                    "the passed seed is either not an integer or is not between 0 and UINT_MAX"
                    )

        # set up cache hook
        receive.cache_hook = self._cache_manager.cacher

        # a PoV was provided
        if self.pov_file is not None:
            self.pov_file = TracerPoV(self.pov_file)
            self.pov = True
        else:
            self.pov = False

        # internal project object, useful for obtaining certain kinds of info
        self._p = angr.Project(self.binary)

        self.base = None
        self.tracer_qemu = None
        self.tracer_qemu_path = None
        self._setup()

        l.debug("accumulating basic block trace...")
        l.debug("self.tracer_qemu_path: %s", self.tracer_qemu_path)

        # does the input cause a crash?
        self.crash_mode = False
        # if the input causes a crash, what address does it crash at?
        self.crash_addr = None

        # CGC flag data
        self.cgc_flag_bytes = [claripy.BVS("cgc-flag-byte-%d" % i, 8) for i in xrange(0x1000)]

        # content of the magic flag page as reported by QEMU
        # we need this to keep symbolic traces following the same path
        # as their dynamic counterpart
        self._magic_content = None

        # will set crash_mode correctly
        self.trace = self.dynamic_trace()

        l.info("trace consists of %d basic blocks", len(self.trace))

        self.preconstraints = []

        # map of variable string names to preconstraints, for re-applying
{'fraction_non_alphanumeric': 0.05952156715012243, 'fraction_numerical': 0.0033904690148803917, 'mean_word_length': 2.2906724511930587, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3693956', 'n_tokens_mistral': 2961, 'n_tokens_neox': 2844, 'n_words': 1037}