def _reset_must_terminate(self, amount_var: PythonVar) -> None: """Reset ``MustTerminate`` permission to its original level. .. note:: Implication is needed because in Silicon if callee took all permission, the ``exhale acc(..., none)`` would fail, even though this exhale does nothing. """ if obligation_config.disable_termination_check: return predicate = self._get_must_terminate_predicate() original_amount = sil.PermVar(amount_var) perm = sil.CurrentPerm(predicate) - original_amount exhale = sil.Exhale(sil.Implies( sil.CurrentPerm(predicate) > sil.NoPerm(), sil.Acc(predicate, perm))) info = self._to_info('Reset MustTerminate amount to original level.') self._append_statement(exhale, info=info)
def _add_leak_check(self) -> None: """Add leak checks to invariant.""" reference_name = self._ctx.actual_function.get_fresh_name('_r') leak_check = self._obligation_manager.create_leak_check(reference_name) loop_check_before = sil.BoolVar( self._loop_obligation_info.loop_check_before_var) termination_flag = sil.BoolVar( self._loop_obligation_info.termination_flag_var) if not obligation_config.disable_loop_context_leak_check: must_terminate = self._obligation_manager.must_terminate_obligation predicate = must_terminate.create_predicate_access( self._obligation_info.current_thread_var) termination_leak_check = sil.CurrentPerm(predicate) == sil.NoPerm() loop_cond = self._loop_obligation_info.construct_loop_condition() before_loop_leak_check = sil.InhaleExhale( sil.TrueLit(), sil.Implies( loop_check_before, sil.BigOr([ termination_flag, sil.Not(loop_cond), sil.BigAnd([termination_leak_check, leak_check]) ]))) info = self._to_info('Leak check for context.') position = self._to_position( conversion_rules=rules.OBLIGATION_LOOP_CONTEXT_LEAK_CHECK_FAIL) self._obligation_loop.append_invariants([ before_loop_leak_check.translate(self._translator, self._ctx, position, info) ]) if not obligation_config.disable_loop_body_leak_check: body_leak_check = sil.InhaleExhale( sil.TrueLit(), sil.Implies(sil.Not(loop_check_before), leak_check)) info = self._to_info('Leak check for loop body.') position = self._to_position( conversion_rules=rules.OBLIGATION_LOOP_BODY_LEAK_CHECK_FAIL) self._obligation_loop.append_invariants([ body_leak_check.translate(self._translator, self._ctx, position, info) ])
def _add_caller_leak_check(self) -> None: """Add a leak check. Check that if callee is not terminating, caller has no obligations. """ if obligation_config.disable_call_context_leak_check: return # MustTerminate leak check. must_terminate = self._obligation_manager.must_terminate_obligation cthread = self._obligation_info.current_thread_var predicate = must_terminate.create_predicate_access(cthread) termination_leak_check = sil.CurrentPerm(predicate) == sil.NoPerm() # Other obligations leak check. reference_name = self._python_method.get_fresh_name('_r') leak_check = self._obligation_manager.create_leak_check(reference_name) if self._python_method.interface: if must_terminate.is_interface_method_terminating( self._python_method.interface_dict): exhale = self._obligation_info.caller_measure_map.check( sil.RefVar(self._obligation_info.current_thread_var), sil.RawIntExpression(1)) else: exhale = sil.BigAnd([termination_leak_check, leak_check]) else: # Termination condition. tcond = self._obligation_info.create_termination_check(False) # Combination. exhale = sil.BigOr( [tcond, sil.BigAnd([termination_leak_check, leak_check])]) check = sil.InhaleExhale(sil.TrueLit(), exhale) # Translate to Silver. node = self.get_function_node() position = self._translator.to_position( node, self._ctx, rules=rules.OBLIGATION_CALL_LEAK_CHECK_FAIL) info = self._translator.to_info(["Caller side leak check"], self._ctx) precondition = check.translate(self._translator, self._ctx, position, info) self._obligation_method.append_preconditions([precondition])
def _bounded_positive(self) -> sil.BoolExpression: return sil.CurrentPerm(self._bounded) > sil.NoPerm()
def _unbounded_positive(self) -> sil.BoolExpression: assert self._unbounded is not None return sil.CurrentPerm(self._unbounded) > sil.NoPerm()