Пример #1
0
 def test_message_field_condition(self) -> None:
     self.assertEqual(ETHERNET_FRAME.field_condition(INITIAL), TRUE)
     self.assertEqual(
         ETHERNET_FRAME.field_condition(Field("TPID")),
         Equal(Variable("Type_Length_TPID"), Number(33024, 16)),
     )
     self.assertEqual(
         ETHERNET_FRAME.field_condition(Field("Type_Length")),
         Or(
             NotEqual(Variable("Type_Length_TPID"), Number(33024, 16)),
             Equal(Variable("Type_Length_TPID"), Number(33024, 16)),
         ),
     )
     self.assertEqual(
         ETHERNET_FRAME.field_condition(Field("Payload")),
         Or(
             And(
                 Or(
                     NotEqual(Variable("Type_Length_TPID"), Number(33024, 16)),
                     Equal(Variable("Type_Length_TPID"), Number(33024, 16)),
                 ),
                 LessEqual(Variable("Type_Length"), Number(1500)),
             ),
             And(
                 Or(
                     NotEqual(Variable("Type_Length_TPID"), Number(33024, 16)),
                     Equal(Variable("Type_Length_TPID"), Number(33024, 16)),
                 ),
                 GreaterEqual(Variable("Type_Length"), Number(1536)),
             ),
         ),
     )
Пример #2
0
 def test_expr_variables(self) -> None:
     self.assertEqual(
         Or(
             Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42)))
         ).variables(),
         [Variable("Y"), Variable("X")],
     )
     self.assertEqual(
         Or(
             Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42)))
         ).variables(),
         [Variable("Y"), Variable("X")],
     )
     self.assertEqual(
         Or(
             Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42)))
         ).variables(),
         [Variable("Y"), Variable("X")],
     )
     self.assertEqual(
         Or(
             Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(1)))
         ).variables(),
         [Variable("Y"), Variable("X")],
     )
Пример #3
0
 def test_expr_variables_duplicates(self) -> None:
     self.assertEqual(
         And(Variable("X"), Variable("Y"), Variable("X")).variables(),
         [Variable("X"), Variable("Y")],
     )
     self.assertEqual(
         Or(Variable("X"), Variable("Y"), Variable("X")).variables(),
         [Variable("X"), Variable("Y")],
     )
     self.assertEqual(
         Add(Variable("X"), Variable("Y"), Variable("X")).variables(),
         [Variable("X"), Variable("Y")],
     )
     self.assertEqual(
         Mul(Variable("X"), Variable("Y"), Variable("X")).variables(),
         [Variable("X"), Variable("Y")],
     )
     self.assertEqual(Sub(Variable("X"), Variable("X")).variables(), [Variable("X")])
     self.assertEqual(Div(Variable("X"), Variable("X")).variables(), [Variable("X")])
     self.assertEqual(
         Or(
             Greater(Variable("X"), Number(42)), And(TRUE, Less(Variable("X"), Number(1)))
         ).variables(),
         [Variable("X")],
     )
Пример #4
0
 def constraints(self, name: str, proof: bool = False) -> Expr:
     if proof:
         return And(
             And(*[Equal(Variable(l), v) for l, v in self.literals.items()]),
             Or(*[Equal(Variable(name), Variable(l)) for l in self.literals.keys()]),
         )
     return TRUE
Пример #5
0
def enumeration_functions(enum: Enumeration) -> List[Subprogram]:
    common_precondition = And(
        Less(Value('Offset'), Number(8)),
        Equal(
            Length('Buffer'),
            Add(
                Div(Add(Size(enum.base_name), Value('Offset'), Number(-1)),
                    Number(8)), Number(1))))

    control_expression = LogCall(
        f'Convert_To_{enum.base_name} (Buffer, Offset)')

    validation_expression: Expr
    if enum.always_valid:
        validation_expression = Value('True')
    else:
        validation_cases: List[Tuple[Expr, Expr]] = []
        validation_cases.extend(
            (value, Value('True')) for value in enum.literals.values())
        validation_cases.append((Value('others'), Value('False')))

        validation_expression = CaseExpression(control_expression,
                                               validation_cases)
    validation_function = ExpressionFunction(
        f'Valid_{enum.name}', 'Boolean', [('Buffer', 'Types.Bytes'),
                                          ('Offset', 'Natural')],
        validation_expression, [Precondition(common_precondition)])

    function_name = f'Convert_To_{enum.name}'
    parameters = [('Buffer', 'Types.Bytes'), ('Offset', 'Natural')]
    precondition = Precondition(
        And(common_precondition,
            LogCall(f'Valid_{enum.name} (Buffer, Offset)')))
    conversion_cases: List[Tuple[Expr, Expr]] = []
    conversion_function: Subprogram

    if enum.always_valid:
        conversion_cases.extend((value, Aggregate(Value('True'), Value(key)))
                                for key, value in enum.literals.items())
        conversion_cases.append(
            (Value('others'), Aggregate(Value('False'), Value('Raw'))))

        conversion_function = Function(
            function_name, enum.name, parameters,
            [Declaration('Raw', enum.base_name, control_expression)],
            [ReturnStatement(CaseExpression(Value('Raw'), conversion_cases))],
            [precondition])
    else:
        conversion_cases.extend(
            (value, Value(key)) for key, value in enum.literals.items())
        conversion_cases.append(
            (Value('others'), LogCall(f'Unreachable_{enum.name}')))

        conversion_function = ExpressionFunction(
            function_name, enum.name, parameters,
            CaseExpression(control_expression, conversion_cases),
            [precondition])

    return [validation_function, conversion_function]
Пример #6
0
def valid_variants(field: Field) -> Iterator[LogExpr]:
    for variant_id, variant in field.variants.items():
        expression: LogExpr = LogCall(
            f'Valid_{field.name}_{variant_id} (Buffer)')
        if field.condition is not TRUE:
            expression = And(expression, field.condition)
        yield expression.simplified(variant.facts).simplified(
            value_to_call_facts([(field.name, variant_id)] + variant.previous))
Пример #7
0
def test_and() -> None:
    assert_equal(
        And(TRUE, FALSE, TRUE).z3expr(),
        z3.And(z3.BoolVal(True), z3.BoolVal(False), z3.BoolVal(True)),
    )
    assert_equal(
        And(TRUE, TRUE, TRUE).z3expr(),
        z3.And(z3.BoolVal(True), z3.BoolVal(True), z3.BoolVal(True)),
    )
    assert_equal(And(TRUE, TRUE).z3expr(), z3.And(z3.BoolVal(True), z3.BoolVal(True)))
Пример #8
0
def field_accessor_functions(field: Field,
                             package_name: str) -> List[Subprogram]:
    precondition = Precondition(
        And(COMMON_PRECONDITION, LogCall(f'Valid_{field.name} (Buffer)')))

    functions: List[Subprogram] = []
    if isinstance(field.type, Array):
        for attribute in ['First', 'Last']:
            functions.append(
                ExpressionFunction(
                    f'Get_{field.name}_{attribute}', 'Types.Index_Type',
                    [('Buffer', 'Types.Bytes')],
                    IfExpression([(
                        LogCall(f'Valid_{field.name}_{variant_id} (Buffer)'),
                        LogCall(
                            f'Get_{field.name}_{variant_id}_{attribute} (Buffer)'
                        )) for variant_id in field.variants],
                                 'Unreachable_Types_Index_Type'),
                    [precondition]))

        body: List[Statement] = [
            Assignment('First', MathCall(f'Get_{field.name}_First (Buffer)')),
            Assignment('Last', MathCall(f'Get_{field.name}_Last (Buffer)'))
        ]
        postcondition = Postcondition(
            And(
                Equal(Value('First'),
                      MathCall(f'Get_{field.name}_First (Buffer)')),
                Equal(Value('Last'),
                      MathCall(f'Get_{field.name}_Last (Buffer)'))))
        if 'Payload' not in field.type.name:
            predicate = f'{package_name}.{field.type.name}.Is_Contained (Buffer (First .. Last))'
            body.append(PragmaStatement('Assume', [predicate]))
            postcondition.expr = And(postcondition.expr, LogCall(predicate))

        functions.append(
            Procedure(f'Get_{field.name}', [('Buffer', 'Types.Bytes'),
                                            ('First', 'out Types.Index_Type'),
                                            ('Last', 'out Types.Index_Type')],
                      [], body, [precondition, postcondition]))

    else:
        functions.append(
            ExpressionFunction(
                f'Get_{field.name}', field.type.name,
                [('Buffer', 'Types.Bytes')],
                IfExpression(
                    [(LogCall(f'Valid_{field.name}_{variant_id} (Buffer)'),
                      MathCall(f'Get_{field.name}_{variant_id} (Buffer)'))
                     for variant_id in field.variants],
                    f'Unreachable_{field.type.name}'), [precondition]))

    return functions
Пример #9
0
    def constraints(self, name: str, proof: bool = False) -> Expr:
        if proof:
            return And(
                GreaterEqual(Variable(name), self.first), LessEqual(Variable(name), self.last)
            )

        c: Expr = TRUE
        if self.first.simplified() != self.base_first.simplified():
            c = GreaterEqual(Variable(name), self.first)
        if self.last.simplified() != self.base_last.simplified():
            c = And(c, LessEqual(Variable(name), self.last))
        return c.simplified()
Пример #10
0
 def test_and(self) -> None:
     self.assertEqual(
         And(TRUE, FALSE, TRUE).z3expr(),
         z3.And(z3.BoolVal(True), z3.BoolVal(False), z3.BoolVal(True)),
     )
     self.assertEqual(
         And(TRUE, TRUE, TRUE).z3expr(),
         z3.And(z3.BoolVal(True), z3.BoolVal(True), z3.BoolVal(True)),
     )
     self.assertEqual(
         And(TRUE, TRUE).z3expr(), z3.And(z3.BoolVal(True),
                                          z3.BoolVal(True)))
Пример #11
0
 def test_ass_expr_converted(self) -> None:
     self.assertEqual(
         And(Variable("X"), Number(1)).converted(
             lambda x: Name(x.name) if isinstance(x, Variable) else x
         ),
         And(Name("X"), Number(1)),
     )
     self.assertEqual(
         Mul(Variable("X"), Number(1)).converted(
             lambda x: Name("Y") if x == Mul(Variable("X"), Number(1)) else x
         ),
         Name("Y"),
     )
Пример #12
0
def test_expr_contains() -> None:
    assert Variable("X") in Or(
        Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42)))
    )
    assert Variable("Z") not in Or(
        Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42)))
    )
    assert Less(Variable("X"), Number(42)) in Or(
        Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42)))
    )
    assert Less(Variable("Z"), Number(42)) not in Or(
        Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(1)))
    )
Пример #13
0
    def __init__(self, name: str, first: MathExpr, last: MathExpr,
                 size: MathExpr) -> None:
        first_num = first.simplified()
        if not isinstance(first_num, Number):
            raise ModelError(f'first of "{name}" contains variable')
        last_num = last.simplified()
        if not isinstance(last_num, Number):
            raise ModelError(f'last of "{name}" contains variable')
        if first_num < Number(0):
            raise ModelError(f'first of "{name}" negative')
        if first_num > last_num:
            raise ModelError(f'range of "{name}" negative')
        size_num = size.simplified()
        if not isinstance(size_num, Number):
            raise ModelError(f'size of "{name}" contains variable')
        if log(int(last_num) + 1) / log(2) > int(size_num):
            raise ModelError(f'size for "{name}" too small')
        super().__init__(name)
        self.__first = first
        self.__last = last
        self.__size = size

        constraints: LogExpr = TRUE
        if self.first.simplified() != self.base_first.simplified():
            constraints = GreaterEqual(Value(self.name), self.first)
        if self.last.simplified() != self.base_last.simplified():
            constraints = And(constraints,
                              LessEqual(Value(self.name), self.last))
        self.__constraints = constraints.simplified()
Пример #14
0
    def create_structural_valid_function() -> UnitPart:
        specification = FunctionSpecification(
            "Structural_Valid",
            "Boolean",
            [Parameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")],
        )

        return UnitPart(
            [SubprogramDeclaration(specification)],
            [
                ExpressionFunctionDeclaration(
                    specification,
                    And(
                        Or(*[
                            Equal(
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "State"),
                                Variable(s),
                            ) for s in ("S_Valid", "S_Structural_Valid")
                        ])),
                )
            ],
        )
Пример #15
0
    def create_verify_message_procedure(
            message: Message, context_invariant: Sequence[Expr]) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify_Message", [InOutParameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Postcondition(
                            And(
                                Equal(
                                    Call("Has_Buffer", [Variable("Ctx")]),
                                    Old(Call("Has_Buffer", [Variable("Ctx")])),
                                ),
                                *context_invariant,
                            )),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [],
                    [
                        CallStatement(
                            "Verify",
                            [Variable("Ctx"),
                             Variable(f.affixed_name)]) for f in message.fields
                    ],
                )
            ],
        )
Пример #16
0
    def create_composite_accessor_procedures(self, composite_fields: Sequence[Field]) -> UnitPart:
        def specification(field: Field) -> ProcedureSpecification:
            return ProcedureSpecification(f"Get_{field.name}", [Parameter(["Ctx"], "Context")])

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f),
                    [
                        Precondition(
                            And(
                                VALID_CONTEXT,
                                Call("Has_Buffer", [Name("Ctx")]),
                                Call("Present", [Name("Ctx"), Name(f.affixed_name)]),
                            )
                        )
                    ],
                    [
                        FormalSubprogramDeclaration(
                            ProcedureSpecification(
                                f"Process_{f.name}", [Parameter([f.name], self.types.bytes)]
                            )
                        )
                    ],
                )
                for f in composite_fields
            ],
            [
                SubprogramBody(
                    specification(f),
                    [
                        ObjectDeclaration(
                            ["First"],
                            self.types.index,
                            Call(
                                self.types.byte_index,
                                [Selected(Indexed("Ctx.Cursors", Name(f.affixed_name)), "First")],
                            ),
                            True,
                        ),
                        ObjectDeclaration(
                            ["Last"],
                            self.types.index,
                            Call(
                                self.types.byte_index,
                                [Selected(Indexed("Ctx.Cursors", Name(f.affixed_name)), "Last")],
                            ),
                            True,
                        ),
                    ],
                    [
                        CallStatement(
                            f"Process_{f.name}",
                            [Slice("Ctx.Buffer.all", Name("First"), Name("Last"))],
                        )
                    ],
                )
                for f in composite_fields
            ],
        )
Пример #17
0
 def assign(self, value: str, check: bool = True) -> None:
     prefixed_value = (
         ID(value) if value.startswith(str(self._type.package))
         or not self.__imported or self.__builtin else self._type.package *
         value)
     if Variable(prefixed_value) not in self.literals:
         raise KeyError(f"{value} is not a valid enum value")
     r = (And(*self._type.constraints(
         "__VALUE__", check, not self.__imported)).substituted(
             mapping={
                 **self.literals,
                 **{
                     Variable("__VALUE__"):
                     self._type.literals[prefixed_value.name]
                 },
                 **{
                     Length("__VALUE__"): self._type.size
                 },
             }).simplified())
     assert r == TRUE
     self._value = (
         str(prefixed_value) if self.__imported and not self.__builtin else
         str(prefixed_value.name),
         self._type.literals[prefixed_value.name],
     )
Пример #18
0
def test_ass_expr_findall() -> None:
    assert_equal(
        And(Equal(Variable("X"), Number(1)), Variable("Y"), Number(2)).findall(
            lambda x: isinstance(x, Number)
        ),
        [Number(1), Number(2)],
    )
Пример #19
0
def variant_accessor_functions(field: Field, variant_id: str,
                               variant: Variant) -> List[Subprogram]:

    first_byte, last_byte, offset = field_location(field.name, variant_id,
                                                   variant)

    name = f'Get_{field.name}_{variant_id}'
    precondition = Precondition(
        And(COMMON_PRECONDITION,
            LogCall(f'Valid_{field.name}_{variant_id} (Buffer)')))

    functions: List[Subprogram] = []
    if isinstance(field.type, Array):
        functions.append(
            ExpressionFunction(f'{name}_First', 'Types.Index_Type',
                               [('Buffer', 'Types.Bytes')], first_byte,
                               [precondition]))
        functions.append(
            ExpressionFunction(f'{name}_Last', 'Types.Index_Type',
                               [('Buffer', 'Types.Bytes')], last_byte,
                               [precondition]))
    else:
        functions.append(
            ExpressionFunction(
                name, field.type.name, [('Buffer', 'Types.Bytes')],
                Convert(
                    field.type.name if field.type.constraints == TRUE else
                    field.type.base_name, 'Buffer', first_byte, last_byte,
                    offset), [precondition]))
    return functions
Пример #20
0
def test_conditionally_unreachable_field_outgoing_multi() -> None:
    f2 = Field(ID("F2", Location((90, 12))))
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), f2,
             LessEqual(Variable("F1"), Number(32), Location((66, 3)))),
        Link(Field("F1"), Field("F3"), Greater(Variable("F1"), Number(32))),
        Link(
            f2,
            Field("F3"),
            And(
                Greater(Variable("F1"), Number(32)),
                LessEqual(Variable("F1"), Number(48)),
                location=Location((22, 34)),
            ),
        ),
        Link(f2, FINAL, Greater(Variable("F1"), Number(48))),
        Link(Field("F3"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): MODULAR_INTEGER,
        Field("F3"): MODULAR_INTEGER,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'<stdin>:90:12: model: error: unreachable field "F2" in "P.M"\n'
        r"<stdin>:90:12: model: info: path 0 [(]F1 -> F2[)]:\n"
        r'<stdin>:66:3: model: info: unsatisfied "F1 <= 32"\n'
        r'<stdin>:90:12: model: info: unsatisfied "[(]F1 > 32 and F1 <= 48[)] or F1 > 48"',
    )
Пример #21
0
def public_context_predicate() -> Expr:
    return And(
        GreaterEqual(Call(const.TYPES_BYTE_INDEX, [Variable("First")]), Variable("Buffer_First")),
        LessEqual(Call(const.TYPES_BYTE_INDEX, [Variable("Last")]), Variable("Buffer_Last")),
        LessEqual(Variable("First"), Variable("Last")),
        LessEqual(Variable("Last"), Div(Last(const.TYPES_BIT_INDEX), Number(2))),
    )
Пример #22
0
 def valid_path_to_next_field_condition(
     self, message: Message, field: Field, field_type: Type
 ) -> Sequence[Expr]:
     return [
         If(
             [
                 (
                     l.condition,
                     And(
                         Equal(
                             Call("Predecessor", [Name("Ctx"), Name(l.target.affixed_name)],),
                             Name(field.affixed_name),
                         ),
                         Call("Valid_Next", [Name("Ctx"), Name(l.target.affixed_name)])
                         if l.target != FINAL
                         else TRUE,
                     ),
                 )
             ]
         ).simplified(
             {
                 **{
                     Variable(field.name): Call("Convert", [Name("Value")])
                     if isinstance(field_type, Enumeration) and field_type.always_valid
                     else Name("Value")
                 },
                 **self.public_substitution(message),
             }
         )
         for l in message.outgoing(field)
         if l.target != FINAL
     ]
Пример #23
0
    def create_scalar_accessor_functions(scalar_fields: Mapping[Field, Scalar]) -> UnitPart:
        def specification(field: Field, field_type: Type) -> FunctionSpecification:
            return FunctionSpecification(
                f"Get_{field.name}", field_type.full_name, [Parameter(["Ctx"], "Context")]
            )

        def result(field: Field, field_type: Type) -> Expr:
            value = Selected(
                Indexed("Ctx.Cursors", Name(field.affixed_name)), f"Value.{field.name}_Value"
            )
            if isinstance(field_type, Enumeration):
                return Call("Convert", [value])
            return value

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification(f, t),
                    [
                        Precondition(
                            And(VALID_CONTEXT, Call("Valid", [Name("Ctx"), Name(f.affixed_name)]))
                        )
                    ],
                )
                for f, t in scalar_fields.items()
            ],
            [
                ExpressionFunctionDeclaration(specification(f, t), result(f, t))
                for f, t in scalar_fields.items()
            ],
        )
Пример #24
0
def contains_function(name: str, pdu: str, field: str, sdu: str,
                      condition: LogExpr) -> Subprogram:

    success_statements: List[Statement] = [ReturnStatement(TRUE)]
    aspects: List[Aspect] = [
        Precondition(
            And(LogCall(f'{pdu}.Is_Contained (Buffer)'),
                LogCall(f'{pdu}.Is_Valid (Buffer)')))
    ]
    if sdu != 'null':
        success_statements.insert(
            0,
            PragmaStatement('Assume', [(
                f'{sdu}.Is_Contained (Buffer ({pdu}.Get_{field}_First (Buffer)'
                f' .. {pdu}.Get_{field}_Last (Buffer)))')]))
        aspects.append(
            Postcondition(
                IfExpression([
                    (LogCall(f'{name}\'Result'),
                     LogCall((f'{sdu}.Is_Contained (Buffer ('
                              f'{pdu}.Get_{field}_First (Buffer)'
                              f' .. {pdu}.Get_{field}_Last (Buffer)))')))
                ])))

    return Function(name, 'Boolean', [('Buffer', 'Types.Bytes')], [], [
        IfStatement([(condition, success_statements)]),
        ReturnStatement(FALSE)
    ], aspects)
Пример #25
0
 def test_message_incoming(self) -> None:
     self.assertEqual(ETHERNET_FRAME.incoming(INITIAL), [])
     self.assertEqual(
         ETHERNET_FRAME.incoming(Field("Type_Length")),
         [
             Link(
                 Field("Type_Length_TPID"),
                 Field("Type_Length"),
                 NotEqual(Variable("Type_Length_TPID"), Number(0x8100, 16)),
                 first=First("Type_Length_TPID"),
             ),
             Link(Field("TCI"), Field("Type_Length")),
         ],
     )
     self.assertEqual(
         ETHERNET_FRAME.incoming(FINAL),
         [
             Link(
                 Field("Payload"),
                 FINAL,
                 And(
                     GreaterEqual(Div(Length("Payload"), Number(8)), Number(46)),
                     LessEqual(Div(Length("Payload"), Number(8)), Number(1500)),
                 ),
             )
         ],
     )
Пример #26
0
    def __prove_field_positions(self) -> None:
        for f in self.__fields:
            for p, l in [(p, p[-1]) for p in self.__paths[f] if p]:
                path_expressions = And(*[self.__link_expression(l) for l in p])
                length = self.__target_length(l)
                positive = If(
                    [
                        (
                            And(
                                self.__type_constraints(And(path_expressions, length)),
                                path_expressions,
                            ),
                            GreaterEqual(length, Number(0)),
                        )
                    ],
                    TRUE,
                )
                result = positive.forall()
                if result != ProofResult.sat:
                    path_message = " -> ".join([l.target.name for l in p])
                    message = str(positive.simplified()).replace("\n\t", "")
                    raise ModelError(
                        f'negative length for field "{f.name}" on path {path_message}'
                        f' in "{self.full_name}" ({result}: {message})'
                    )

                first = self.__target_first(l)
                start = If(
                    [
                        (
                            And(
                                self.__type_constraints(And(path_expressions, first)),
                                path_expressions,
                            ),
                            GreaterEqual(first, First("Message")),
                        )
                    ],
                    TRUE,
                )
                result = start.forall()
                if result != ProofResult.sat:
                    path_message = " -> ".join([l.target.name for l in p])
                    message = str(start.simplified()).replace("\n\t", "")
                    raise ModelError(
                        f'start of field "{f.name}" on path {path_message} before'
                        f' message start in "{self.full_name} ({result}: {message})'
                    )
Пример #27
0
    def __prove_coverage(self) -> None:
        """
        Prove that the fields of a message cover all message bits, i.e. there are no holes in the
        message definition.

        Idea: Let f be the bits covered by the message. By definition
            (1) f >= Message'First and f <= Message'Last
        holds. For every field add a conjunction of the form
            (2) Not(f >= Field'First and f <= Field'Last),
        effectively pruning the range that this field covers from the bit range of the message. For
        the overall expression, prove that it is false for all f, i.e. no bits are left.
        """
        for path in [p[:-1] for p in self.__paths[FINAL] if p]:
            # Calculate (1)
            message_range = And(
                GreaterEqual(Variable("f"), First("Message")),
                LessEqual(Variable("f"), Last("Message")),
            )
            # Calculate (2) for all fields
            fields = And(
                *[
                    Not(
                        And(
                            GreaterEqual(Variable("f"), self.__target_first(l)),
                            LessEqual(Variable("f"), self.__target_last(l)),
                        )
                    )
                    for l in path
                ]
            )
            # Define that the end of the last field of a path is the end of the message
            last_field = Equal(self.__target_last(path[-1]), Last("Message"))
            # Constraints for links and types
            path_expressions = self.__with_constraints(
                And(*[self.__link_expression(l) for l in path])
            )

            # Coverage expression must be False, i.e. no bits left
            coverage = Not(And(*[fields, last_field, path_expressions, message_range]))
            result = coverage.forall()
            if result != ProofResult.sat:
                path_message = " -> ".join([l.target.name for l in path])
                message = str(coverage).replace("\n\t", "")
                raise ModelError(
                    f"path {path_message} does not cover whole message"
                    f' in "{self.full_name}" ({result}: {message})'
                )
Пример #28
0
 def bounded_composite_setter_preconditions(message: Message,
                                            field: Field) -> Sequence[Expr]:
     return [
         Call(
             "Field_Condition",
             [
                 Variable("Ctx"),
                 NamedAggregate(("Fld", Variable(field.affixed_name)))
             ] + ([Variable("Length")]
                  if common.length_dependent_condition(message) else []),
         ),
         GreaterEqual(
             Call("Available_Space",
                  [Variable("Ctx"),
                   Variable(field.affixed_name)]),
             Variable("Length"),
         ),
         LessEqual(
             Add(
                 Call("Field_First",
                      [Variable("Ctx"),
                       Variable(field.affixed_name)]),
                 Variable("Length"),
             ),
             Div(Last(const.TYPES_BIT_INDEX), Number(2)),
         ),
         Or(*[
             And(
                 *[
                     Call("Valid",
                          [Variable("Ctx"),
                           Variable(field.affixed_name)])
                     for field in message.fields
                     if Variable(field.name) in l.condition.variables()
                 ],
                 l.condition.substituted(
                     mapping={
                         Variable(field.name): Call(f"Get_{field.name}",
                                                    [Variable("Ctx")])
                         for field in message.fields
                         if Variable(field.name) in l.condition.variables()
                     }),
             ) for l in message.incoming(field)
             if Last("Message") in l.length
         ]),
         Equal(
             Mod(
                 Call("Field_First",
                      [Variable("Ctx"),
                       Variable(field.affixed_name)]),
                 Size(const.TYPES_BYTE),
             ),
             Number(1),
         ),
         Equal(
             Mod(Variable("Length"), Size(const.TYPES_BYTE)),
             Number(0),
         ),
     ]
Пример #29
0
 def test_expr_contains(self) -> None:
     self.assertTrue(
         Variable("X")
         in Or(Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42))))
     )
     self.assertFalse(
         Variable("Z")
         in Or(Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42))))
     )
     self.assertTrue(
         Less(Variable("X"), Number(42))
         in Or(Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(42))))
     )
     self.assertFalse(
         Less(Variable("Z"), Number(42))
         in Or(Greater(Variable("Y"), Number(42)), And(TRUE, Less(Variable("X"), Number(1))))
     )
Пример #30
0
def buffer_constraints(last: MathExpr) -> LogExpr:
    last = last.simplified()
    index_constraint = LessEqual(First('Buffer'),
                                 Div(Last('Types.Index_Type'), Number(2)))
    if last != Last('Buffer'):
        length_constraint = GreaterEqual(
            Length('Buffer'), Add(last, -First('Buffer'), Number(1)))
        return And(length_constraint, index_constraint)
    return index_constraint