コード例 #1
0
def test_conditionally_unreachable_field_enum_last() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), Field("F2"), Equal(Last("F1"), Last("Message"))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): ENUMERATION,
        Field("F2"): ENUMERATION,
    }
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'model: error: unreachable field "F2" in "P.M"\n'
        r"model: info: path 0 [(]F1 -> F2[)]:\n"
        r'model: info: unsatisfied "F2\'Last = [(][(][(]F1\'Last [+] 1[)] [+] 8[)][)] - 1"\n'
        r'model: info: unsatisfied "Message\'Last >= F2\'Last"\n'
        r'model: info: unsatisfied "F1\'Last = Message\'Last"\n'
        r'model: error: unreachable field "Final" in "P.M"\n'
        r"model: info: path 0 [(]F1 -> F2 -> Final[)]:\n"
        r'model: info: unsatisfied "F2\'Last = [(][(][(]F1\'Last [+] 1[)] [+] 8[)][)] - 1"\n'
        r'model: info: unsatisfied "Message\'Last >= F2\'Last"\n'
        r'model: info: unsatisfied "F1\'Last = Message\'Last"',
    )
コード例 #2
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_slice_simplified() -> None:
    assert_equal(
        Slice(
            Variable("Buffer"), First("Buffer"), Add(Last("Buffer"), Add(Number(21), Number(21))),
        ).simplified(),
        Slice(Variable("Buffer"), First("Buffer"), Add(Last("Buffer"), Number(42))),
    )
コード例 #3
0
ファイル: test_expression.py プロジェクト: senier/RecordFlux
 def test_slice_simplified(self) -> None:
     self.assertEqual(
         Slice(
             "Buffer", First("Buffer"), Add(Last("Buffer"), Add(Number(21), Number(21)))
         ).simplified(),
         Slice("Buffer", First("Buffer"), Add(Last("Buffer"), Number(42))),
     )
コード例 #4
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_named_aggregate_substituted() -> None:
    assert_equal(
        NamedAggregate(("First", First("X"))).substituted(
            lambda x: Number(42) if x == NamedAggregate(("First", First("X"))) else x
        ),
        Number(42),
    )
    assert_equal(
        NamedAggregate(("First", First("X"))).substituted(
            lambda x: Number(42) if x == First("X") else x
        ),
        NamedAggregate(("First", Number(42))),
    )
    assert_equal(
        NamedAggregate(("First", First("X"))).substituted(
            lambda x: Variable(f"P_{x}")
            if isinstance(x, Variable)
            else (
                NamedAggregate(*[*x.elements, (ID("Last"), Last("Y"))])
                if isinstance(x, NamedAggregate)
                else x
            )
        ),
        NamedAggregate(("First", First("P_X")), ("Last", Last("P_Y"))),
    )
コード例 #5
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),
         ),
     ]
コード例 #6
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
コード例 #7
0
def field_location(field_name: str, variant_id: str,
                   variant: Variant) -> Tuple[MathExpr, MathExpr, int]:

    value_to_call = value_to_call_facts([(field_name, variant_id)] +
                                        variant.previous)
    first_byte = variant.facts[First(field_name)].to_bytes().simplified(
        value_to_call)
    last_byte = variant.facts[Last(field_name)].to_bytes().simplified(
        value_to_call)
    offset = calculate_offset(variant.facts[Last(field_name)])
    return (first_byte, last_byte, offset)
コード例 #8
0
ファイル: common.py プロジェクト: senier/RecordFlux
    def substitution(self, message: Message, prefix: bool = True) -> Mapping[Name, Expr]:
        def prefixed(name: str) -> Expr:
            return Selected(Name("Ctx"), name) if prefix else Name(name)

        first = prefixed("First")
        last = prefixed("Last")
        cursors = prefixed("Cursors")

        return {
            **{First("Message"): first},
            **{Last("Message"): last},
            **{
                First(f.name): Selected(Indexed(cursors, Name(f.affixed_name)), "First")
                for f in message.fields
            },
            **{
                Last(f.name): Selected(Indexed(cursors, Name(f.affixed_name)), "Last")
                for f in message.fields
            },
            **{
                Length(f.name): Add(
                    Sub(
                        Selected(Indexed(cursors, Name(f.affixed_name)), "Last"),
                        Selected(Indexed(cursors, Name(f.affixed_name)), "First"),
                    ),
                    Number(1),
                )
                for f in message.fields
            },
            **{
                Variable(f.name): Call(
                    self.types.bit_length,
                    [Selected(Indexed(cursors, Name(f.affixed_name)), f"Value.{f.name}_Value")],
                )
                for f, t in message.types.items()
                if not isinstance(t, Enumeration)
            },
            **{
                Variable(f.name): Call(
                    self.types.bit_length,
                    [Selected(Indexed(cursors, Name(f.affixed_name)), f"Value.{f.name}_Value")],
                )
                for f, t in message.types.items()
                if isinstance(t, Enumeration)
            },
            **{
                Variable(l): Call(self.types.bit_length, [Call("Convert", [Name(l)])])
                for l in itertools.chain.from_iterable(
                    t.literals.keys() for t in message.types.values() if isinstance(t, Enumeration)
                )
            },
        }
コード例 #9
0
ファイル: model.py プロジェクト: senier/RecordFlux
 def __link_expression(self, link: Link) -> Expr:
     name = link.target.name
     return And(
         *[
             Equal(First(name), self.__target_first(link)),
             Equal(Length(name), self.__target_length(link)),
             Equal(Last(name), self.__target_last(link)),
             GreaterEqual(First("Message"), Number(0)),
             GreaterEqual(Last("Message"), Last(name)),
             GreaterEqual(Last("Message"), First("Message")),
             Equal(Length("Message"), Add(Sub(Last("Message"), First("Message")), Number(1))),
             link.condition,
         ]
     )
コード例 #10
0
def test_no_verification_icmp_checksum(
        icmp_checksum_message_value: MessageValue,
        icmp_message: Message) -> None:
    test_data = (
        b"\x47\xb4\x67\x5e\x00\x00\x00\x00"
        b"\x4a\xfc\x0d\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17"
        b"\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27"
        b"\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37")
    icmp_checksum_unv = MessageValue(
        icmp_message.copy(
            structure=[
                Link(l.source,
                     l.target,
                     condition=And(l.condition, ValidChecksum("Checksum")))
                if l.target == FINAL else l for l in icmp_message.structure
            ],
            checksums={
                ID("Checksum"): [
                    ValueRange(First("Tag"), Sub(First("Checksum"),
                                                 Number(1))),
                    Size("Checksum"),
                    ValueRange(Add(Last("Checksum"), Number(1)),
                               Last("Message")),
                ]
            },
        ),
        skip_verification=True,
    )
    icmp_checksum_message_value.set_checksum_function(
        {"Checksum": icmp_checksum_function})
    icmp_checksum_message_value.set("Tag", "Echo_Request")
    icmp_checksum_message_value.set("Code_Zero", 0)
    icmp_checksum_message_value.set("Identifier", 5)
    icmp_checksum_message_value.set("Sequence_Number", 1)
    icmp_checksum_message_value.set("Data", test_data)
    icmp_checksum_unv.set_checksum_function(
        {"Checksum": icmp_checksum_function})
    icmp_checksum_unv.set("Tag", "Echo_Request")
    icmp_checksum_unv.set("Code_Zero", 0)
    icmp_checksum_unv.set("Checksum", 0)
    icmp_checksum_unv.set("Identifier", 5)
    icmp_checksum_unv.set("Sequence_Number", 1)
    icmp_checksum_unv.set("Data", test_data)
    icmp_checksum_unv.update_checksums()
    assert icmp_checksum_unv.valid_message
    assert icmp_checksum_unv.get(
        "Checksum") == icmp_checksum_message_value.get("Checksum")
    assert icmp_checksum_unv.bytestring == icmp_checksum_message_value.bytestring
コード例 #11
0
    def test_field_coverage_2(self) -> None:
        foo_type = ModularInteger("P.Foo", Pow(Number(2), Number(32)))
        structure = [
            Link(INITIAL, Field("F1")),
            Link(Field("F1"), Field("F2")),
            Link(Field("F2"), Field("F4"), Greater(Variable("F1"),
                                                   Number(100))),
            Link(
                Field("F2"),
                Field("F3"),
                LessEqual(Variable("F1"), Number(100)),
                first=Add(Last("F2"), Number(64)),
            ),
            Link(Field("F3"), Field("F4")),
            Link(Field("F4"), FINAL),
        ]

        types = {
            Field("F1"): foo_type,
            Field("F2"): foo_type,
            Field("F3"): foo_type,
            Field("F4"): foo_type,
        }
        with mock.patch("rflx.model.Message._Message__verify_conditions",
                        lambda x: None):
            with self.assertRaisesRegex(
                    ModelError,
                    "^path F1 -> F2 -> F3 -> F4 does not cover whole message"):
                Message("P.M", structure, types)
コード例 #12
0
def test_field_coverage_2(monkeypatch: Any) -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), Field("F2")),
        Link(Field("F2"), Field("F4"), Greater(Variable("F1"), Number(100))),
        Link(
            Field("F2"),
            Field("F3"),
            LessEqual(Variable("F1"), Number(100)),
            first=Add(Last("F2"), Number(64)),
        ),
        Link(Field("F3"), Field("F4")),
        Link(Field("F4"), FINAL),
    ]

    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): MODULAR_INTEGER,
        Field("F3"): MODULAR_INTEGER,
        Field("F4"): MODULAR_INTEGER,
    }
    monkeypatch.setattr(Message, "_AbstractMessage__verify_conditions",
                        lambda x: None)
    assert_message_model_error(
        structure,
        types,
        r"^"
        r"model: error: path does not cover whole message\n"
        r'model: info: on path: "F1"\n'
        r'model: info: on path: "F2"\n'
        r'model: info: on path: "F3"\n'
        r'model: info: on path: "F4"'
        r"$",
    )
コード例 #13
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))),
    )
コード例 #14
0
ファイル: model.py プロジェクト: senier/RecordFlux
    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})'
                )
コード例 #15
0
def parse_attribute(string: str, location: int, tokens: list) -> Attribute:
    if tokens[2] == 'First':
        return First(tokens[0])
    if tokens[2] == 'Last':
        return Last(tokens[0])
    if tokens[2] == 'Length':
        return Length(tokens[0])
    raise ParseFatalException(string, location, 'unexpected attribute')
コード例 #16
0
def create_facts(facts: Dict[Attribute, MathExpr],
                 edge: Edge) -> Dict[Attribute, MathExpr]:
    facts = dict(facts)
    facts[Length(edge.target.name)] = edge.length.simplified(facts)
    facts[First(edge.target.name)] = edge.first.simplified(facts)
    facts[Last(edge.target.name)] = Add(edge.first, edge.length,
                                        Number(-1)).simplified(facts)
    return facts
コード例 #17
0
def parse_attribute(string: str, location: int,
                    tokens: ParseResults) -> Attribute:
    if tokens[2] == "First":
        return First(tokens[0])
    if tokens[2] == "Last":
        return Last(tokens[0])
    if tokens[2] == "Length":
        return Length(tokens[0])
    raise ParseFatalException(string, location, "unexpected attribute")
コード例 #18
0
def test_valid_use_message_first_last() -> None:
    structure = [
        Link(
            INITIAL,
            Field("Verify_Data"),
            length=Add(Sub(Last("Message"), First("Message")), Number(1)),
        ),
        Link(Field("Verify_Data"), FINAL),
    ]
    types = {Field("Verify_Data"): Opaque()}
    Message("P.M", structure, types)
コード例 #19
0
 def setter_preconditions(self, field: Field) -> Sequence[Expr]:
     return [
         VALID_CONTEXT,
         Not(Constrained("Ctx")),
         Call("Has_Buffer", [Name("Ctx")]),
         Call("Valid_Next", [Name("Ctx"), Name(field.affixed_name)]),
         LessEqual(
             Call("Field_Last", [Name("Ctx"), Name(field.affixed_name)]),
             Div(Last(self.types.bit_index), Number(2)),
         ),
     ]
コード例 #20
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_attribute_substituted() -> None:
    assert_equal(First("X").substituted(lambda x: Number(42) if x == First("X") else x), Number(42))
    assert_equal(
        -First("X").substituted(lambda x: Number(42) if x == First("X") else x), Number(-42)
    )
    assert_equal(
        First("X").substituted(lambda x: Call("Y") if x == Variable("X") else x), First(Call("Y")),
    )
    assert_equal(
        -First("X").substituted(lambda x: Call("Y") if x == Variable("X") else x),
        -First(Call("Y")),
    )
    assert_equal(
        -First("X").substituted(
            lambda x: Variable(f"P_{x}")
            if isinstance(x, Variable)
            else (Last(x.prefix) if isinstance(x, First) else x)
        ),
        -Last(Variable("P_X")),
    )
コード例 #21
0
ファイル: test_expression.py プロジェクト: kug1977/RecordFlux
def test_attribute() -> None:
    assert isinstance(Size("X"), Attribute)
    assert isinstance(Length("X"), Attribute)
    assert isinstance(First("X"), Attribute)
    assert isinstance(Last("X"), Attribute)
    assert isinstance(Range("X"), Attribute)
    assert isinstance(Old("X"), Attribute)
    assert isinstance(Result("X"), Attribute)
    assert isinstance(Constrained("X"), Attribute)
    assert First("X") == First(Variable("X"))
    assert First("X") == First(ID("X"))
    assert First("X") == First(Variable(ID("X")))
コード例 #22
0
 def setter_preconditions(field: Field) -> Sequence[Expr]:
     return [
         Not(Constrained("Ctx")),
         Call("Has_Buffer", [Variable("Ctx")]),
         Call("Valid_Next", [Variable("Ctx"),
                             Variable(field.affixed_name)]),
         LessEqual(
             Call("Field_Last",
                  [Variable("Ctx"),
                   Variable(field.affixed_name)]),
             Div(Last(const.TYPES_BIT_INDEX), Number(2)),
         ),
     ]
コード例 #23
0
ファイル: common.py プロジェクト: senier/RecordFlux
 def public_substitution(self, message: Message) -> Mapping[Name, Expr]:
     return {
         **{First("Message"): Selected(Name("Ctx"), "First")},
         **{Last("Message"): Selected(Name("Ctx"), "Last")},
         **{
             First(f.name): Call("Field_First", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Last(f.name): Call("Field_Last", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Length(f.name): Call("Field_Length", [Name("Ctx"), Name(f.affixed_name)])
             for f in message.fields
         },
         **{
             Variable(f.name): Call(
                 self.types.bit_length, [Call(f"Get_{f.name}", [Name("Ctx")])]
             )
             for f, t in message.types.items()
             if not isinstance(t, Enumeration)
         },
         **{
             Variable(f.name): Call(
                 self.types.bit_length, [Call("Convert", [Call(f"Get_{f.name}", [Name("Ctx")])])]
             )
             for f, t in message.types.items()
             if isinstance(t, Enumeration)
         },
         **{
             Variable(l): Call(self.types.bit_length, [Call("Convert", [Name(l)])])
             for l in itertools.chain.from_iterable(
                 t.literals.keys() for t in message.types.values() if isinstance(t, Enumeration)
             )
         },
     }
コード例 #24
0
 def bounded_composite_setter_preconditions(
     self, message: Message, field: Field
 ) -> Sequence[Expr]:
     return [
         Call(
             "Field_Condition",
             [Name("Ctx"), NamedAggregate(("Fld", Name(field.affixed_name)))]
             + ([Name("Length")] if length_dependent_condition(message) else []),
         ),
         GreaterEqual(
             Call("Available_Space", [Name("Ctx"), Name(field.affixed_name)]), Name("Length"),
         ),
         LessEqual(
             Add(Call("Field_First", [Name("Ctx"), Name(field.affixed_name)]), Name("Length"),),
             Div(Last(self.types.bit_index), Number(2)),
         ),
         Or(
             *[
                 And(
                     *[
                         Call("Valid", [Name("Ctx"), Name(field.affixed_name)])
                         for field in message.fields
                         if Variable(field.name) in l.condition.variables()
                     ],
                     l.condition.simplified(
                         {
                             Variable(field.name): Call(f"Get_{field.name}", [Name("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
             ]
         ),
     ]
コード例 #25
0
def create_ethernet_pdu() -> PDU:
    uint48 = ModularInteger('UINT48', Pow(Number(2), Number(48)))
    uint16 = RangeInteger('UINT16',
                          Number(0),
                          Sub(Pow(Number(2), Number(16)), Number(1)),
                          Number(16))
    payload_array = Array('Payload_Array')

    initial = InitialNode()
    destination = Node('Destination', uint48)
    source = Node('Source', uint48)
    tpid = Node('TPID', uint16)
    tci = Node('TCI', uint16)
    ether_type = Node('EtherType', uint16)
    payload = Node('Payload', payload_array)

    initial.edges = [Edge(destination)]
    destination.edges = [Edge(source)]
    source.edges = [Edge(tpid)]
    tpid.edges = [Edge(tci,
                       Equal(Value('TPID'), Number(0x8100))),
                  Edge(ether_type,
                       NotEqual(Value('TPID'), Number(0x8100)),
                       first=First('TPID'))]
    tci.edges = [Edge(ether_type)]
    ether_type.edges = [Edge(payload,
                             LessEqual(Value('EtherType'), Number(1500)),
                             Mul(LengthValue('EtherType'), Number(8))),
                        Edge(payload,
                             GreaterEqual(Value('EtherType'), Number(1536)),
                             Sub(Last('Message'), Last('EtherType')))]
    payload.edges = [Edge(FINAL,
                          And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)),
                              LessEqual(Div(Length('Payload'), Number(8)), Number(1500))))]

    return PDU('Ethernet.Frame', initial)
コード例 #26
0
def message_length_function(variants: List[Variant]) -> Subprogram:
    condition_expressions: List[Tuple[LogExpr, Expr]] = []

    for variant in variants:
        condition = variant_condition(variant)
        length = Add(
            Last(variant.previous[-1][0]), -First(variant.previous[0][0]),
            Number(1)).simplified(variant.facts).simplified(
                value_to_call_facts(variant.previous)).to_bytes().simplified()
        condition_expressions.append((condition, length))

    return ExpressionFunction(
        'Message_Length', 'Types.Length_Type', [('Buffer', 'Types.Bytes')],
        IfExpression(condition_expressions, 'Unreachable_Types_Length_Type'),
        [Precondition(And(COMMON_PRECONDITION, LogCall('Is_Valid (Buffer)')))])
コード例 #27
0
ファイル: model.py プロジェクト: senier/RecordFlux
 def __prove_overlays(self) -> None:
     for f in (INITIAL, *self.__fields):
         for p, l in [(p, p[-1]) for p in self.__paths[f] if p]:
             if l.first != UNDEFINED and isinstance(l.first, First):
                 path_expressions = And(*[self.__link_expression(l) for l in p])
                 overlaid = If(
                     [(path_expressions, Equal(self.__target_last(l), Last(l.first.name)))], TRUE
                 )
                 result = overlaid.forall()
                 if result != ProofResult.sat:
                     message = str(overlaid).replace("\n", "")
                     raise ModelError(
                         f'field "{f.name}" not congruent with overlaid field '
                         f'"{l.first.name}" in "{self.full_name}"'
                         f" ({result}: {message})"
                     )
コード例 #28
0
ファイル: typevalue.py プロジェクト: kug1977/RecordFlux
 def __update_simplified_mapping(self) -> None:
     field_values: Mapping[Name, Expr] = {
         **{
             Variable(k): v.typeval.expr
             for k, v in self._fields.items() if isinstance(
                 v.typeval, ScalarValue) and v.set
         },
         **{
             Length(k): v.typeval.size
             for k, v in self._fields.items() if v.set
         },
         **{First(k): v.first
            for k, v in self._fields.items() if v.set},
         **{Last(k): v.last
            for k, v in self._fields.items() if v.set},
     }
     self._simplified_mapping = {**field_values, **self.__type_literals}
コード例 #29
0
def test_invalid_first_is_last() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"),
             Field("F2"),
             first=Last(ID("F1", Location((11, 20))))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): MODULAR_INTEGER,
    }
    assert_message_model_error(
        structure,
        types,
        r'^<stdin>:11:20: model: error: invalid First for field "F2"$',
    )
コード例 #30
0
def variant_validation_function(field: Field, variant_id: str,
                                variant: Variant) -> Subprogram:

    type_constraints: LogExpr = TRUE

    if field.type.constraints != TRUE or isinstance(field.type, Enumeration):
        first_byte, last_byte, offset = field_location(field.name, variant_id,
                                                       variant)

        if field.type.constraints != TRUE:
            convert = Convert(field.type.base_name, 'Buffer', first_byte,
                              last_byte, offset)
            type_constraints = field.type.constraints.simplified(
                {Value(field.type.name): convert})

        if isinstance(field.type, Enumeration):
            type_constraints = And(
                type_constraints,
                LogCall((f'Valid_{field.type.name} (Buffer ({first_byte}'
                         f' .. {last_byte}), {offset})')))

    value_to_call = value_to_call_facts([(field.name, variant_id)] +
                                        variant.previous)

    return ExpressionFunction(
        f'Valid_{field.name}_{variant_id}', 'Boolean',
        [('Buffer', 'Types.Bytes')],
        And(
            LogCall(
                f'Valid_{variant.previous[-1][0]}_{variant.previous[-1][1]} (Buffer)'
            ) if variant.previous else TRUE,
            And(
                And(
                    buffer_constraints(variant.facts[Last(
                        field.name)].to_bytes()).simplified(value_to_call),
                    variant.condition.simplified(
                        variant.facts).simplified(value_to_call)),
                type_constraints)).simplified(),
        [Precondition(COMMON_PRECONDITION)])