示例#1
0
 def find_model_value_for_function(self, expr: z3.ExprRef) -> object:
     # TODO: this need to go into a tree node that returns UNKNOWN or worse
     # (because it just returns one example function; it's not covering the space)
     if self.solver.check() != z3.sat:
         raise CrosshairInternal('model unexpectedly became unsatisfiable')
     finterp = self.solver.model()[expr]
     if self.solver.check() != z3.sat:
         raise CrosshairInternal(
             'could not confirm model satisfiability after fixing value')
     return finterp
示例#2
0
    def enabled_enforcement(self):
        prev = self.fns_enforcing
        assert prev is None
        self.fns_enforcing = set()
        if not COMPOSITE_TRACER.set_enabled(self, True):
            raise CrosshairInternal("Cannot enable enforcement")

        try:
            yield None
        finally:
            self.fns_enforcing = prev
            if not COMPOSITE_TRACER.set_enabled(self, prev):
                raise CrosshairInternal(
                    "Tracing handler stack is inconsistent")
示例#3
0
def pool_worker_main(item: WorkItemInput, output: multiprocessing.queues.Queue) -> None:
    try:
        # TODO figure out a more reliable way to suppress this. Redirect output?
        # Ignore ctrl-c in workers to reduce noisy tracebacks (the parent will kill us):
        signal.signal(signal.SIGINT, signal.SIG_IGN)

        if hasattr(os, 'nice'): # analysis should run at a low priority
            os.nice(10)
        set_debug(False)
        filename, options, deadline = item
        stats: Counter[str] = Counter()
        options.stats = stats
        _, module_name = extract_module_from_file(filename)
        try:
            module = load_by_qualname(module_name)
        except NotFound:
            return
        except ErrorDuringImport as e:
            orig, frame = e.args
            message = AnalysisMessage(MessageType.IMPORT_ERR, str(orig), frame.filename, frame.lineno, 0, '')
            output.put((filename, stats, [message]))
            debug(f'Not analyzing "{filename}" because import failed: {e}')
            return
        messages = analyze_any(module, options)
        output.put((filename, stats, messages))
    except BaseException as e:
        raise CrosshairInternal(
            'Worker failed while analyzing ' + filename) from e
示例#4
0
def register_type(typ: Type,
                  creator: Union[Type, Callable]) -> None:
    assert typ is origin_of(typ), \
            f'Only origin types may be registered, not "{typ}": try "{origin_of(typ)}" instead.'
    if typ in _SIMPLE_PROXIES:
        raise CrosshairInternal(f'Duplicate type "{typ}" registered')
    _SIMPLE_PROXIES[typ] = creator
示例#5
0
def register_patch(entity: object, patch_value: Callable, attr_name: Optional[str] = None):
    if attr_name in _PATCH_REGISTRATIONS[IdentityWrapper(entity)]:
        raise CrosshairInternal(f'Doubly registered patch: {object} . {attr_name}')
    if attr_name is None:
        attr_name = getattr(patch_value, '__name__', None)
        assert attr_name is not None
    _PATCH_REGISTRATIONS[IdentityWrapper(entity)][attr_name] = patch_value
示例#6
0
 def find_model_value_for_function(self, expr: z3.ExprRef) -> object:
     # TODO: this need to go into a tree node that returns UNKNOWN or worse
     # (because it just returns one example function; it's not covering the space)
     if not solver_is_sat(self.solver):
         raise CrosshairInternal(
             'model unexpectedly became unsatisfiable')
     return self.solver.model()[expr]
示例#7
0
 def __init__(self, rand: random.Random, expr: z3.ExprRef, solver: z3.Solver):
     if self.condition_value is None:
         if not solver_is_sat(solver):
             debug('bad solver', solver.sexpr())
             raise CrosshairInternal('unexpected un sat')
         self.condition_value = solver.model().evaluate(expr, model_completion=True)
     WorstResultNode.__init__(self, rand, expr == self.condition_value, solver)
示例#8
0
 def __init__(self, rand: random.Random, expr: z3.ExprRef,
              solver: z3.Solver):
     if not solver_is_sat(solver):
         debug("Solver unexpectedly unsat; solver state:", solver.sexpr())
         raise CrosshairInternal("Unexpected unsat from solver")
     self.condition_value = solver.model().evaluate(expr,
                                                    model_completion=True)
     self._stats_key = f"realize_{expr}" if z3.is_const(expr) else None
     WorstResultNode.__init__(self, rand, expr == self.condition_value,
                              solver)
示例#9
0
    def find_model_value_for_function(self, expr: z3.ExprRef) -> object:
        if not solver_is_sat(self.solver):
            raise CrosshairInternal("model unexpectedly became unsatisfiable")
        # TODO: this need to go into a tree node that returns UNKNOWN or worse
        # (because it just returns one example function; it's not covering the space)

        # TODO: note this is also unsound - after completion, the solver isn't
        # bound to the returned interpretation. (but don't know how to add the
        # right constraints) Maybe just use arrays instead.
        return self.solver.model()[expr]
示例#10
0
 def __init__(self, rand: random.Random, expr: z3.ExprRef, solver: z3.Solver):
     RandomizedBinaryPathNode.__init__(self, rand)
     notexpr = z3.Not(expr)
     could_be_true = solver_is_sat(solver, expr)
     could_be_false = solver_is_sat(solver, notexpr)
     if (not could_be_true) and (not could_be_false):
         debug(' *** Reached impossible code path *** ')
         debug('Current solver state:\n', str(solver))
         raise CrosshairInternal('Reached impossible code path')
     elif not could_be_true:
         self.forced_path = False
     elif not could_be_false:
         self.forced_path = True
示例#11
0
 def __init__(self, rand: random.Random, expr: z3.ExprRef,
              solver: z3.Solver):
     super().__init__(rand)
     notexpr = z3.Not(expr)
     could_be_true = solver_is_sat(solver, expr)
     could_be_false = solver_is_sat(solver, notexpr)
     if (not could_be_true) and (not could_be_false):
         debug(" *** Reached impossible code path *** ")
         debug("Current solver state:\n", str(solver))
         raise CrosshairInternal("Reached impossible code path")
     elif not could_be_true:
         self.forced_path = False
     elif not could_be_false:
         self.forced_path = True
     self._expr = expr  # note: this is only used for debugging
示例#12
0
def pool_worker_main(item: WorkItemInput,
                     output: multiprocessing.queues.Queue) -> None:
    try:
        # TODO figure out a more reliable way to suppress this. Redirect output?
        # Ignore ctrl-c in workers to reduce noisy tracebacks (the parent will kill us):
        signal.signal(signal.SIGINT, signal.SIG_IGN)

        if hasattr(os, 'nice'):  # analysis should run at a low priority
            os.nice(10)
        set_debug(False)
        (stats, messages) = pool_worker_process_item(item)
        filename = item[0]
        output.put((filename, stats, messages))
    except BaseException as e:
        raise CrosshairInternal('Worker failed while analyzing ' +
                                filename) from e
示例#13
0
    def choose_possible(self, expr: z3.ExprRef, favor_true=False) -> bool:
        with self.framework():
            if time.time() > self.execution_deadline:
                debug('Path execution timeout after making ',
                      len(self.choices_made), ' choices.')
                raise PathTimeout
            if self.solver.check() != z3.sat:
                debug('bad solver', self.solver)
                raise CrosshairInternal('unexpected un sat')
            notexpr = z3.Not(expr)
            if self.search_position.is_stem():
                self.search_position = self.search_position.grow_into(
                    WorstResultNode(self._random, expr, self.solver))

            self.search_position = self.search_position.simplify()
            node = self.search_position
            # NOTE: format_stack() is more human readable, but it pulls source file contents,
            # so it is (1) slow, and (2) unstable when source code changes while we are checking.
            statedesc = '\n'.join(map(str, traceback.extract_stack()))
            assert isinstance(node, SearchTreeNode)
            if node.statehash is None:
                node.statehash = statedesc
            else:
                if node.statehash != statedesc:
                    debug(self.choices_made)
                    debug(' *** Begin Not Deterministic Debug *** ')
                    debug('     First state: ', len(node.statehash))
                    debug(node.statehash)
                    debug('     Last state: ', len(statedesc))
                    debug(statedesc)
                    debug('     Stack Diff: ')
                    import difflib
                    debug('\n'.join(
                        difflib.context_diff(node.statehash.split('\n'),
                                             statedesc.split('\n'))))
                    debug(' *** End Not Deterministic Debug *** ')
                    raise NotDeterministic()
            choose_true, stem = node.choose(favor_true=favor_true)
            assert isinstance(self.search_position, SearchTreeNode)
            self.choices_made.append(self.search_position)
            self.search_position = stem
            expr = expr if choose_true else notexpr
            #debug('CHOOSE', expr)
            self.add(expr)
            return choose_true
示例#14
0
文件: core.py 项目: moreati/CrossHair
def analyze_any(entity: object,
                options: AnalysisOptions) -> List[AnalysisMessage]:
    if inspect.isclass(entity):
        return analyze_class(cast(Type, entity), options)
    elif inspect.isfunction(entity):
        self_class: Optional[type] = None
        fn = cast(Callable, entity)
        if fn.__name__ != fn.__qualname__:
            self_thing = walk_qualname(sys.modules[fn.__module__],
                                       fn.__qualname__.split('.')[-2])
            assert isinstance(self_thing, type)
            self_class = self_thing
        return analyze_function(fn, options, self_type=self_class)
    elif inspect.ismodule(entity):
        return analyze_module(cast(types.ModuleType, entity), options)
    else:
        raise CrosshairInternal('Entity type not analyzable: ' +
                                str(type(entity)))
示例#15
0
 def __init__(self, rand: random.Random, expr: z3.ExprRef,
              solver: z3.Solver):
     RandomizedBinaryPathNode.__init__(self, rand)
     notexpr = z3.Not(expr)
     true_sat, false_sat = solver.check(expr), solver.check(notexpr)
     if true_sat == z3.unknown or false_sat == z3.unknown:
         raise UnknownSatisfiability
     could_be_true = (true_sat == z3.sat)
     could_be_false = (false_sat == z3.sat)
     if (not could_be_true) and (not could_be_false):
         debug(' *** Reached impossible code path *** ', true_sat,
               false_sat, expr)
         debug('Current solver state:\n', str(solver))
         raise CrosshairInternal('Reached impossible code path')
     elif not could_be_true:
         self.forced_path = False
     elif not could_be_false:
         self.forced_path = True
示例#16
0
文件: main.py 项目: ckeeter/CrossHair
def pool_worker_main(item: WorkItemInput,
                     output: multiprocessing.queues.Queue) -> None:
    try:
        # TODO figure out a more reliable way to suppress this. Redirect output?
        # Ignore ctrl-c in workers to reduce noisy tracebacks (the parent will kill us):
        signal.signal(signal.SIGINT, signal.SIG_IGN)
        if hasattr(os,
                   'nice'):  # <- is this the right way to detect availability?
            os.nice(10)  # analysis should run at a low priority
        set_debug(False)
        member, options, deadline = item
        stats: Counter[str] = Counter()
        options.stats = stats
        try:
            fn = member.get_member()
        except NotFound:
            return
        messages = analyze_any(fn, options)
        output.put((member, stats, messages))
    except BaseException as e:
        raise CrosshairInternal('Worker failed while analyzing ' +
                                member.qual_name) from e
示例#17
0
 def choose_possible(self, expr: z3.ExprRef, favor_true=False) -> bool:
     with self.framework():
         notexpr = z3.Not(expr)
         true_sat, false_sat = self.check(expr), self.check(notexpr)
         could_be_true = (true_sat == z3.sat)
         could_be_false = (false_sat == z3.sat)
         if (not could_be_true) and (not could_be_false):
             raise CrosshairInternal('Reached impossible code path')
         else:
             log, idx = self.execution_log, self.log_index
             if idx >= len(log):
                 if idx == len(log):
                     debug('Precise path replay unsuccessful.')
                 return False
             debug('decide_true = ', self.execution_log[self.log_index])
             decide_true = (self.execution_log[self.log_index] == '1')
             self.log_index += 1
         expr = expr if decide_true else notexpr
         debug('REPLAY CHOICE', expr)
         self.add(expr)
         if not self.solver.check():
             debug('Precise path replay unsuccessful.')
         return decide_true
示例#18
0
 def uniq(self):
     self.next_uniq += 1
     if self.next_uniq >= 1000000:
         raise CrosshairInternal('Exhausted var space')
     return '{:06d}'.format(self.next_uniq)