Beispiel #1
0
    def _translate_waitlevel_method(
            self, expr: sil.PermExpression, node: ast.Compare,
            ctx: Context) -> sil.BoolExpression:
        """Translate ``WaitLevel() < Level()`` in method contract."""
        position = self.to_position(node, ctx)
        info = self.no_info(ctx)

        obligation_info = ctx.actual_function.obligation_info
        guard = obligation_info.get_wait_level_guard(node.left)
        exhale = self._create_level_below_inex(
            guard, expr, obligation_info.residue_level, ctx)
        translated_exhale = exhale.translate(self, ctx, position, info)
        if ctx.ignore_waitlevel_constraints:
            return sil.TrueLit()
        if ctx.obligation_context.is_translating_posts:
            obligation_info.add_postcondition(translated_exhale)
            caller_inhale = sil.InhaleExhale(
                sil.PermVar(obligation_info.current_wait_level) < expr,
                sil.TrueLit())
            return caller_inhale
        else:
            obligation_info.add_precondition(translated_exhale)
            body_inhale = sil.InhaleExhale(
                sil.PermVar(obligation_info.residue_level) < expr,
                sil.TrueLit())
            return body_inhale
Beispiel #2
0
 def construct_obligation_bound(self) -> sil.Statement:
     """Construct statement for bounding obligation."""
     if self._credit_only:
         return sil.Exhale(sil.TrueLit())
     return sil.If(
         self._unbounded_positive,
         [sil.Exhale(self._unbounded_acc),
          sil.Inhale(self._bounded_acc)], [])
Beispiel #3
0
 def _create_level_below_inex(self, guard: sil.BoolExpression,
                              expr: sil.PermExpression, level: PythonVar,
                              ctx: Context) -> sil.BoolExpression:
     return sil.InhaleExhale(
         sil.TrueLit(),
         sil.Implies(guard,
                     self.create_level_below(expr, sil.PermVar(level),
                                             ctx)))
Beispiel #4
0
 def initialize_current_wait_level(self,
                                   current_wait_level: sil.PermExpression,
                                   residue_level_var: sil.PermExpression,
                                   ctx: Context) -> sil.BoolExpression:
     return sil.InhaleExhale(
         self._create_level_below_equal(current_wait_level,
                                        residue_level_var, ctx),
         sil.TrueLit())
Beispiel #5
0
 def _set_loop_check_before(self) -> None:
     """Set the variable indicating that we are before loop."""
     if obligation_config.disable_all:
         return
     assign = sil.Assign(self._loop_obligation_info.loop_check_before_var,
                         sil.TrueLit())
     info = self._to_info('We are before loop.')
     self._append_statement(assign, info=info)
Beispiel #6
0
 def _construct_inhale(self, fresh: bool) -> sil.Acc:
     """Construct obligation inhale."""
     if self._skip_inhale:
         return sil.TrueLit()
     if self._credit_only:
         return self._credit_acc
     if fresh:
         return self._unbounded_acc
     else:
         return self._bounded_acc
Beispiel #7
0
    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)
            ])
Beispiel #8
0
 def check(self, reference: sil.RefExpression,
           value: sil.IntExpression) -> sil.BoolExpression:
     """Generate a check if current value is smaller than in map."""
     if (obligation_config.disable_measures or
             obligation_config.disable_measure_check):
         return sil.TrueLit()
     args = [
         sil.CallArg('map', self._measure_var_type,
                     sil.AnyVar(self._map_var)),
         sil.CallArg('key', sil.REF, reference),
         sil.CallArg('value', sil.INT, value),
     ]
     return sil.BoolCall('Measure$check', args)
Beispiel #9
0
    def construct_use_method_bounded(
            self, measure_check: sil.BoolExpression,
            is_postconditon: bool) -> sil.BoolExpression:
        """Construct inhale exhale pair for use in method contract.

        Used for bounded obligations.
        """
        if self._skip_exhale:
            exhale = sil.TrueLit()
        elif self._credit_only:
            exhale = self._credit_acc
        else:
            exhale = self._construct_bounded_exhale(
                measure_check if not is_postconditon else None)
        return sil.InhaleExhale(self._construct_inhale(False), exhale)
Beispiel #10
0
    def construct_use_loop(
            self, measure_check: Optional[sil.BoolExpression],
            loop_check_before_var: sil.BoolVar) -> sil.BoolExpression:
        """Construct inhale exhale pair for use in loop invariant.

        ``measure_check is None`` indicates that obligation is fresh.
        """
        if self._skip_exhale:
            exhale = sil.TrueLit()
        elif self._credit_only:
            exhale = self._credit_acc
        elif measure_check is None:
            exhale = self._construct_unbounded_exhale()
        else:
            exhale = sil.BoolCondExp(
                loop_check_before_var, self._construct_bounded_exhale(None),
                self._construct_bounded_exhale(measure_check))
        inhale = self._construct_inhale(measure_check is None)
        return sil.InhaleExhale(inhale, exhale)
Beispiel #11
0
    def _add_body_leak_check(self) -> None:
        """Add a leak check.

        Check that method body does not leak obligations.
        """
        if obligation_config.disable_method_body_leak_check:
            return
        reference_name = self._python_method.get_fresh_name('_r')
        check = sil.InhaleExhale(
            sil.TrueLit(),
            self._obligation_manager.create_leak_check(reference_name))
        node = self._python_method.node
        assert node
        position = self._translator.to_position(
            node, self._ctx, rules=rules.OBLIGATION_BODY_LEAK_CHECK_FAIL)
        info = self._translator.to_info(["Body leak check."], self._ctx)
        postcondition = check.translate(self._translator, self._ctx, position,
                                        info)
        self._obligation_method.append_postconditions([postcondition])
Beispiel #12
0
    def _translate_waitlevel_loop(
            self, expr: sil.PermExpression, node: ast.Compare,
            ctx: Context) -> sil.BoolExpression:
        """Translate ``WaitLevel() < Level()`` in loop invariant."""
        position = self.to_position(node, ctx)
        info = self.no_info(ctx)

        obligation_info = ctx.obligation_context.current_loop_info
        guard = obligation_info.get_wait_level_guard(node.left)
        context_info = ctx.obligation_context.get_surrounding_loop_info()
        if context_info:
            context_residue_level = context_info.residue_level
        else:
            method_info = ctx.current_function.obligation_info
            context_residue_level = method_info.residue_level
        body_inhale = sil.Inhale(
            sil.Implies(
                guard,
                sil.PermVar(obligation_info.residue_level) < expr))
        obligation_info.prepend_body(
            body_inhale.translate(self, ctx, position, info))
        body_exhale = sil.Implies(
            sil.Not(sil.BoolVar(obligation_info.loop_check_before_var)),
            self._create_level_below_inex(
                guard, expr, obligation_info.residue_level, ctx))
        obligation_info.add_invariant(
            body_exhale.translate(self, ctx, position, info))
        context_inhale = sil.Inhale(
            sil.Implies(
                guard,
                sil.PermVar(context_residue_level) < expr))
        obligation_info.append_after_loop(
            context_inhale.translate(self, ctx, position, info))
        context_exhale = sil.Implies(
            sil.BoolVar(obligation_info.loop_check_before_var),
            self._create_level_below_inex(
                guard, expr, context_residue_level, ctx))
        obligation_info.add_invariant(
            context_exhale.translate(self, ctx, position, info))
        return sil.TrueLit()
Beispiel #13
0
    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])