def make_fake_object(cls: type, varname: str) -> object: constructor = get_smt_proxy_type(cls) try: proxy = constructor() except TypeError as e: # likely the type has a __new__ that expects arguments raise CrosshairUnsupported(f'Unable to proxy {name_of_type(cls)}: {e}') for name, typ in get_type_hints(cls).items(): origin = getattr(typ, '__origin__', None) if origin is Callable: continue value = proxy_for_type( typ, varname + '.' + name + context_statespace().uniq()) object.__setattr__(proxy, name, value) return proxy
def get_smt_proxy_type(cls: type) -> type: if issubclass(cls, SmtProxyMarker): return cls global _SMT_PROXY_TYPES cls_name = name_of_type(cls) if cls not in _SMT_PROXY_TYPES: def symbolic_init(self): self.__class__ = cls class_body = { '__init__': symbolic_init } try: proxy_cls = type(cls_name + '_proxy', (SmtProxyMarker, cls), class_body) except TypeError as e: if 'is not an acceptable base type' in str(e): raise CrosshairUnsupported(f'Cannot subclass {cls_name}') else: raise _SMT_PROXY_TYPES[cls] = proxy_cls return _SMT_PROXY_TYPES[cls]
def __exit__(self, exc_type, exc_value, tb): if isinstance(exc_value, (PostconditionFailed, IgnoreAttempt)): if isinstance(exc_value, PostconditionFailed): # Postcondition : although this indicates a problem, it's with a # subroutine; not this function. # Usualy we want to ignore this because it will be surfaced more locally # in the subroutine. debug( f'Ignoring based on internal failed post condition: {exc_value}' ) self.ignore = True self.analysis = CallAnalysis() return True if isinstance(exc_value, self.expected_exceptions): debug(f'Hit expected exception: {exc_value}') self.ignore = True self.analysis = CallAnalysis(VerificationStatus.CONFIRMED) return True if isinstance(exc_value, TypeError): exc_str = str(exc_value) if ('SmtStr' in exc_str or 'SmtInt' in exc_str or 'SmtFloat' in exc_str or 'expected string or bytes-like object' in exc_str): # Ideally we'd attempt literal strings after encountering this. # See https://github.com/pschanely/CrossHair/issues/8 debug('Proxy intolerace at: ', traceback.format_exc()) raise CrosshairUnsupported('Detected proxy intolerance: ' + exc_str) if isinstance(exc_value, (UnexploredPath, CrosshairInternal, z3.Z3Exception)): return False # internal issue: re-raise if isinstance( exc_value, BaseException): # TODO: should this be "Exception" instead? # Most other issues are assumed to be user-level exceptions: self.user_exc = (exc_value, traceback.extract_tb(sys.exc_info()[2])) self.analysis = CallAnalysis(VerificationStatus.REFUTED) return True # suppress user-level exception return False # re-raise resource and system issues