Пример #1
0
 def test_sub_simplified(self) -> None:
     self.assertEqual(Sub(Number(1), Variable("X")).simplified(), Add(Variable("X"), Number(-1)))
     self.assertEqual(Sub(Variable("X"), Number(1)).simplified(), Add(Variable("X"), Number(-1)))
     self.assertEqual(Sub(Number(6), Number(2)).simplified(), Number(4))
     self.assertEqual(
         Sub(Variable("X"), Variable("Y")).simplified(), Add(Variable("X"), Variable("Y", True))
     )
Пример #2
0
 def test_sub(self) -> None:
     self.assertEqual(
         Sub(Number(6), Number(4)).z3expr(),
         z3.IntVal(6) - z3.IntVal(4))
     self.assertEqual(
         Sub(Number(12), Number(20)).z3expr(),
         z3.IntVal(12) - z3.IntVal(20))
Пример #3
0
def test_sub_simplified() -> None:
    assert Sub(Number(1), Variable("X")).simplified() == Add(Number(1), -Variable("X"))
    assert Sub(Variable("X"), Number(1)).simplified() == Add(Variable("X"), Number(-1))
    assert Sub(Number(6), Number(2)).simplified() == Number(4)
    assert Sub(Variable("X"), Variable("Y")).simplified() == Add(Variable("X"), -Variable("Y"))
    assert (
        Equal(Variable("Q"), Sub(Add(Variable("Y"), Variable("Q")), Variable("Y")))
        .simplified()
        .simplified()
        == TRUE
    )
Пример #4
0
 def test_sub_simplified(self) -> None:
     self.assertEqual(
         Sub(Number(1), Value('X')).simplified(),
         Add(Value('X'), Number(-1)))
     self.assertEqual(
         Sub(Value('X'), Number(1)).simplified(),
         Add(Value('X'), Number(-1)))
     self.assertEqual(Sub(Number(6), Number(2)).simplified(), Number(4))
     self.assertEqual(
         Sub(Value('X'), Value('Y')).simplified(),
         Add(Value('X'), Value('Y', True)))
Пример #5
0
 def test_distributivity_simplified(self) -> None:
     self.assertEqual(
         Add(Sub(Value('X'), Add(Value('X'), Number(1))),
             Add(Value('X'), Number(1))).simplified(), Value('X'))
     self.assertEqual(
         Div(Add(Mul(Value('X'), Number(8)), Number(144)),
             Number(8)).simplified(), Add(Value('X'), Number(18)))
     self.assertEqual(
         Div(Sub(Mul(Value('X'), Number(8)), Number(148)),
             Number(8)).simplified(),
         Add(Value('X'), Div(Number(-148), Number(8))))
Пример #6
0
 def test_bin_expr_converted(self) -> None:
     self.assertEqual(
         Less(Variable("X"), Number(1)).converted(
             lambda x: Name(x.name) if isinstance(x, Variable) else x
         ),
         Less(Name("X"), Number(1)),
     )
     self.assertEqual(
         Sub(Variable("X"), Number(1)).converted(
             lambda x: Name("Y") if x == Sub(Variable("X"), Number(1)) else x
         ),
         Name("Y"),
     )
Пример #7
0
def parse_mathematical_expression(string: str, location: int,
                                  tokens: ParseResults) -> Expr:
    result: List[Expr] = tokens[0]
    while len(result) > 1:
        left = result.pop(0)
        operator = result.pop(0)
        right = result.pop(0)
        assert left.location, f'expression "{left}" without location'
        assert right.location, f'expression "{right}" without location'
        assert left.location.source == right.location.source, "expression with different source"
        locn = Location(left.location.start, left.location.source,
                        left.location.end)
        expression: Expr
        if operator == "+":
            expression = Add(left, right)
            expression.location = locn
        elif operator == "-":
            expression = Sub(left, right, locn)
        elif operator == "*":
            expression = Mul(left, right)
            expression.location = locn
        elif operator == "/":
            expression = Div(left, right, locn)
        elif operator == "**":
            expression = Pow(left, right, locn)
        else:
            raise ParseFatalException(string, location,
                                      "unexpected mathematical operator")
        result.insert(0, expression)
    return result[0]
Пример #8
0
 def test_range_size(self) -> None:
     self.assertEqual(RangeInteger('UINT32',
                                   Number(0),
                                   Sub(Pow(Number(2), Number(32)), Number(1)),
                                   Number(32)
                                   ).size,
                      Number(32))
Пример #9
0
 def test_term_simplified(self) -> None:
     self.assertEqual(
         Add(
             Mul(Number(1), Number(6)), Sub(Variable("X"), Number(10)), Add(Number(1), Number(3))
         ).simplified(),
         Variable("X"),
     )
Пример #10
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")],
     )
Пример #11
0
def test_range_size() -> None:
    assert_equal(
        RangeInteger("P.T", Number(0),
                     Sub(Pow(Number(2), Number(32)), Number(1)),
                     Number(32)).size,
        Number(32),
    )
Пример #12
0
 def field_length(field: Field) -> Expr:
     if public:
         return Call("Field_Length", [Variable("Ctx"), Variable(field.affixed_name)])
     return Add(
         Sub(
             Selected(Indexed(cursors, Variable(field.affixed_name)), "Last"),
             Selected(Indexed(cursors, Variable(field.affixed_name)), "First"),
         ),
         Number(1),
     )
Пример #13
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)
Пример #14
0
def test_bin_expr_substituted() -> None:
    assert_equal(
        Less(Variable("X"), Number(1)).substituted(
            lambda x: Variable(f"P_{x}") if isinstance(x, Variable) else x
        ),
        Less(Variable("P_X"), Number(1)),
    )
    assert_equal(
        Sub(Variable("X"), Number(1)).substituted(
            lambda x: Variable("Y") if x == Sub(Variable("X"), Number(1)) else x
        ),
        Variable("Y"),
    )
    assert_equal(
        NotEqual(Variable("X"), Number(1)).substituted(
            lambda x: Variable(f"P_{x}")
            if isinstance(x, Variable)
            else (Equal(x.left, x.right) if isinstance(x, NotEqual) else x)
        ),
        Equal(Variable("P_X"), Number(1)),
    )
Пример #15
0
def test_mathematical_expression_precedence() -> None:
    assert_equal(
        grammar.mathematical_expression().parseString("A - B * 2**3 - 1")[0],
        Sub(Sub(Variable("A"), Mul(Variable("B"), Pow(Number(2), Number(3)))), Number(1)),
    )
    assert_equal(
        grammar.mathematical_expression().parseString("(A - B) * 2**3 - 1")[0],
        Sub(Mul(Sub(Variable("A"), Variable("B")), Pow(Number(2), Number(3))), Number(1)),
    )
    assert_equal(
        grammar.mathematical_expression().parseString("A - B * 2**(3 - 1)")[0],
        Sub(Variable("A"), Mul(Variable("B"), Pow(Number(2), Sub(Number(3), Number(1))))),
    )
    assert_equal(
        grammar.mathematical_expression().parseString("A - (B * 2)**3 - 1")[0],
        Sub(Sub(Variable("A"), Pow(Mul(Variable("B"), Number(2)), Number(3))), Number(1)),
    )
    assert_equal(
        grammar.mathematical_expression().parseString("A - (B * 2**3 - 1)")[0],
        Sub(Variable("A"), Sub(Mul(Variable("B"), Pow(Number(2), Number(3))), Number(1))),
    )
Пример #16
0
    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)
                )
            },
        }
Пример #17
0
 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,
         ]
     )
Пример #18
0
def test_invalid_negative_field_length_modular() -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"), Field("F2"), length=Sub(Variable("F1"), Number(2))),
        Link(Field("F2"), FINAL),
    ]
    types = {
        Field("F1"): MODULAR_INTEGER,
        Field("F2"): Opaque(),
    }
    assert_message_model_error(
        structure,
        types,
        r'^model: error: negative length for field "F2" [(]F1 -> F2[)]$',
    )
Пример #19
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)
Пример #20
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
Пример #21
0
def test_invalid_negative_field_length_range_integer() -> None:
    o = Field(ID("O", location=Location((44, 3))))
    structure = [
        Link(INITIAL, Field("L")),
        Link(
            Field("L"),
            o,
            length=Mul(Number(8), Sub(Variable("L"), Number(50))),
        ),
        Link(o, FINAL),
    ]
    types = {Field("L"): RANGE_INTEGER, o: Opaque()}
    assert_message_model_error(
        structure,
        types,
        r'^<stdin>:44:3: model: error: negative length for field "O" [(]L -> O[)]$',
    )
Пример #22
0
    def test_field_after_message_start(self) -> None:
        foo_type = ModularInteger("P.Foo", Pow(Number(2), Number(32)))
        structure = [
            Link(INITIAL, Field("F1")),
            Link(Field("F1"),
                 Field("F2"),
                 first=Sub(First("Message"), Number(1000))),
            Link(Field("F2"), FINAL),
        ]

        types = {Field("F1"): foo_type, Field("F2"): foo_type}
        with mock.patch("rflx.model.Message._Message__verify_conditions",
                        lambda x: None):
            with self.assertRaisesRegex(
                    ModelError, '^start of field "F2" on path F1 -> F2 before'
                    " message start"):
                Message("P.M", structure, types)
Пример #23
0
 def field_byte_location_declarations(self) -> Sequence[Declaration]:
     return [
         ExpressionFunctionDeclaration(
             FunctionSpecification("Buffer_First", self.types.index),
             Call(self.types.byte_index, [Name("First")]),
         ),
         ExpressionFunctionDeclaration(
             FunctionSpecification("Buffer_Last", self.types.index),
             Call(self.types.byte_index, [Name("Last")]),
         ),
         ExpressionFunctionDeclaration(
             FunctionSpecification("Offset", self.types.offset),
             Call(
                 self.types.offset,
                 [Mod(Sub(Number(8), Mod(Name("Last"), Number(8))), Number(8))],
             ),
         ),
     ]
Пример #24
0
def field_byte_location_declarations() -> Sequence[Declaration]:
    return [
        ExpressionFunctionDeclaration(
            FunctionSpecification("Buffer_First", const.TYPES_INDEX),
            Call(const.TYPES_BYTE_INDEX, [Variable("First")]),
        ),
        ExpressionFunctionDeclaration(
            FunctionSpecification("Buffer_Last", const.TYPES_INDEX),
            Call(const.TYPES_BYTE_INDEX, [Variable("Last")]),
        ),
        ExpressionFunctionDeclaration(
            FunctionSpecification("Offset", const.TYPES_OFFSET),
            Call(
                const.TYPES_OFFSET,
                [Mod(Sub(Number(8), Mod(Variable("Last"), Number(8))), Number(8))],
            ),
        ),
    ]
Пример #25
0
def test_field_after_message_start(monkeypatch: Any) -> None:
    structure = [
        Link(INITIAL, Field("F1")),
        Link(Field("F1"),
             Field("F2"),
             first=Sub(First("Message"), Number(1000))),
        Link(Field("F2"), FINAL),
    ]

    types = {Field("F1"): MODULAR_INTEGER, Field("F2"): MODULAR_INTEGER}
    monkeypatch.setattr(Message, "_AbstractMessage__verify_conditions",
                        lambda x: None)
    assert_message_model_error(
        structure,
        types,
        r"^"
        r'model: error: negative start for field "F2" [(]F1 -> F2[)]\n'
        r'model: info: unsatisfied "Message\'First - 1000 >= Message\'First"'
        r"$",
    )
Пример #26
0
def parse_mathematical_expression(string: str, location: int,
                                  tokens: list) -> MathExpr:
    result: List[MathExpr] = tokens[0]
    while len(result) > 1:
        left = result.pop(0)
        operator = result.pop(0)
        right = result.pop(0)
        expression: MathExpr
        if operator == '+':
            expression = Add(left, right)
        elif operator == '-':
            expression = Sub(left, right)
        elif operator == '*':
            expression = Mul(left, right)
        elif operator == '/':
            expression = Div(left, right)
        elif operator == '**':
            expression = Pow(left, right)
        else:
            raise ParseFatalException(string, location,
                                      'unexpected mathematical operator')
        result.insert(0, expression)
    return result[0]
Пример #27
0
def parse_mathematical_expression(string: str, location: int,
                                  tokens: ParseResults) -> Expr:
    result: List[Expr] = tokens[0]
    while len(result) > 1:
        left = result.pop(0)
        operator = result.pop(0)
        right = result.pop(0)
        expression: Expr
        if operator == "+":
            expression = Add(left, right)
        elif operator == "-":
            expression = Sub(left, right)
        elif operator == "*":
            expression = Mul(left, right)
        elif operator == "/":
            expression = Div(left, right)
        elif operator == "**":
            expression = Pow(left, right)
        else:
            raise ParseFatalException(string, location,
                                      "unexpected mathematical operator")
        result.insert(0, expression)
    return result[0]
Пример #28
0
    def message_structure_invariant(
        self, message: Message, link: Link = None, prefix: bool = True
    ) -> Expr:
        def prefixed(name: str) -> Expr:
            return Selected(Name("Ctx"), name) if prefix else Name(name)

        if not link:
            return self.message_structure_invariant(message, message.outgoing(INITIAL)[0], prefix)

        source = link.source
        target = link.target

        if target is FINAL:
            return TRUE

        field_type = message.types[target]
        condition = link.condition.simplified(self.substitution(message, prefix))
        length = (
            Size(base_type_name(field_type))
            if isinstance(field_type, Scalar)
            else link.length.simplified(self.substitution(message, prefix))
        )
        first = (
            Name(prefixed("First"))
            if source == INITIAL
            else link.first.simplified(
                {
                    **self.substitution(message, prefix),
                    **{
                        UNDEFINED: Add(
                            Selected(
                                Indexed(prefixed("Cursors"), Name(source.affixed_name)), "Last"
                            ),
                            Number(1),
                        )
                    },
                }
            )
        )

        return If(
            [
                (
                    AndThen(
                        Call(
                            "Structural_Valid",
                            [Indexed(prefixed("Cursors"), Name(target.affixed_name))],
                        ),
                        condition,
                    ),
                    AndThen(
                        Equal(
                            Add(
                                Sub(
                                    Selected(
                                        Indexed(prefixed("Cursors"), Name(target.affixed_name)),
                                        "Last",
                                    ),
                                    Selected(
                                        Indexed(prefixed("Cursors"), Name(target.affixed_name)),
                                        "First",
                                    ),
                                ),
                                Number(1),
                            ),
                            length,
                        ),
                        Equal(
                            Selected(
                                Indexed(prefixed("Cursors"), Name(target.affixed_name)),
                                "Predecessor",
                            ),
                            Name(source.affixed_name),
                        ),
                        Equal(
                            Selected(
                                Indexed(prefixed("Cursors"), Name(target.affixed_name)), "First"
                            ),
                            first,
                        ),
                        *[
                            self.message_structure_invariant(message, l, prefix)
                            for l in message.outgoing(target)
                        ],
                    ),
                )
            ]
        ).simplified()
Пример #29
0
    def test_pdu_fields_ethernet(self) -> None:
        expected = OrderedDict([
            ('Destination',
             Field('Destination',
                   ModularInteger('UINT48', Pow(Number(2), Number(48))),
                   TRUE,
                   {
                       '0':
                       Variant(
                           [],
                           TRUE,
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47)
                           })
                   })),
            ('Source',
             Field('Source',
                   ModularInteger('UINT48', Pow(Number(2), Number(48))),
                   TRUE,
                   {
                       '00':
                       Variant(
                           [
                               ('Destination', '0')
                           ],
                           TRUE,
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95)
                           })
                   })),
            ('TPID',
             Field('TPID',
                   RangeInteger('UINT16',
                                Number(0),
                                Sub(Pow(Number(2), Number(16)), Number(1)),
                                Number(16)),
                   Or(NotEqual(Value('TPID'), Number(0x8100)),
                      Equal(Value('TPID'), Number(0x8100))),
                   {
                       '000':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00')
                           ],
                           TRUE,
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111)
                           })
                   })),
            ('TCI',
             Field('TCI',
                   RangeInteger('UINT16',
                                Number(0),
                                Sub(Pow(Number(2), Number(16)), Number(1)),
                                Number(16)),
                   TRUE,
                   {
                       '0000':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000')
                           ],
                           Equal(Value('TPID'), Number(0x8100)),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('TCI'): Number(16),
                               First('TCI'): Number(112),
                               Last('TCI'): Number(127)
                           })
                   })),
            ('EtherType',
             Field('EtherType',
                   RangeInteger('UINT16',
                                Number(0),
                                Sub(Pow(Number(2), Number(16)), Number(1)),
                                Number(16)),
                   Or(GreaterEqual(Value('EtherType'), Number(1536)),
                      LessEqual(Value('EtherType'), Number(1500))),
                   {
                       '00000':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('TCI', '0000')
                           ],
                           TRUE,
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('TCI'): Number(16),
                               First('TCI'): Number(112),
                               Last('TCI'): Number(127),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(128),
                               Last('EtherType'): Number(143)
                           }),
                       '0001':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000')
                           ],
                           NotEqual(Value('TPID'), Number(0x8100)),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(96),
                               Last('EtherType'): Number(111)
                           })
                   })),
            ('Payload',
             Field('Payload',
                   Array('Payload_Array'),
                   And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)),
                       LessEqual(Div(Length('Payload'), Number(8)), Number(1500))),
                   {
                       '000000':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('TCI', '0000'),
                               ('EtherType', '00000')
                           ],
                           LessEqual(Value('EtherType'), Number(1500)),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('TCI'): Number(16),
                               First('TCI'): Number(112),
                               Last('TCI'): Number(127),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(128),
                               Last('EtherType'): Number(143),
                               Length('Payload'): Mul(LengthValue('EtherType'), Number(8)),
                               First('Payload'): Number(144),
                               Last('Payload'): Add(Mul(LengthValue('EtherType'), Number(8)),
                                                    Number(143))
                           }),
                       '000001':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('TCI', '0000'),
                               ('EtherType', '00000')
                           ],
                           GreaterEqual(Value('EtherType'), Number(1536)),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('TCI'): Number(16),
                               First('TCI'): Number(112),
                               Last('TCI'): Number(127),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(128),
                               Last('EtherType'): Number(143),
                               Length('Payload'): Add(Last('Message'), Number(-143)),
                               First('Payload'): Number(144),
                               Last('Payload'): Last('Message')
                           }),
                       '00010':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('EtherType', '0001')
                           ],
                           LessEqual(Value('EtherType'), Number(1500)),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(96),
                               Last('EtherType'): Number(111),
                               Length('Payload'): Mul(LengthValue('EtherType'), Number(8)),
                               First('Payload'): Number(112),
                               Last('Payload'): Add(Mul(LengthValue('EtherType'), Number(8)),
                                                    Number(111))
                           }),
                       '00011':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('EtherType', '0001')
                           ],
                           GreaterEqual(Value('EtherType'), Number(1536)),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(96),
                               Last('EtherType'): Number(111),
                               Length('Payload'): Add(Last('Message'), Number(-111)),
                               First('Payload'): Number(112),
                               Last('Payload'): Last('Message')
                           })
                   })),
            ('FINAL',
             Field('FINAL',
                   Null(),
                   TRUE,
                   {
                       '0000000':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('TCI', '0000'),
                               ('EtherType', '00000'),
                               ('Payload', '000000')
                           ],
                           And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)),
                               LessEqual(Div(Length('Payload'), Number(8)), Number(1500))),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('TCI'): Number(16),
                               First('TCI'): Number(112),
                               Last('TCI'): Number(127),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(128),
                               Last('EtherType'): Number(143),
                               Length('Payload'): Mul(LengthValue('EtherType'), Number(8)),
                               First('Payload'): Number(144),
                               Last('Payload'): Add(Mul(LengthValue('EtherType'), Number(8)),
                                                    Number(143))
                           }),
                       '0000010':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('TCI', '0000'),
                               ('EtherType', '00000'),
                               ('Payload', '000001')
                           ],
                           And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)),
                               LessEqual(Div(Length('Payload'), Number(8)), Number(1500))),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('TCI'): Number(16),
                               First('TCI'): Number(112),
                               Last('TCI'): Number(127),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(128),
                               Last('EtherType'): Number(143),
                               Length('Payload'): Add(Last('Message'), Number(-143)),
                               First('Payload'): Number(144),
                               Last('Payload'): Last('Message')
                           }),
                       '000100':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('EtherType', '0001'),
                               ('Payload', '00010')
                           ],
                           And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)),
                               LessEqual(Div(Length('Payload'), Number(8)), Number(1500))),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(96),
                               Last('EtherType'): Number(111),
                               Length('Payload'): Mul(LengthValue('EtherType'), Number(8)),
                               First('Payload'): Number(112),
                               Last('Payload'): Add(Mul(LengthValue('EtherType'), Number(8)),
                                                    Number(111))
                           }),
                       '000110':
                       Variant(
                           [
                               ('Destination', '0'),
                               ('Source', '00'),
                               ('TPID', '000'),
                               ('EtherType', '0001'),
                               ('Payload', '00011')
                           ],
                           And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)),
                               LessEqual(Div(Length('Payload'), Number(8)), Number(1500))),
                           {
                               Length('Destination'): Number(48),
                               First('Destination'): Number(0),
                               Last('Destination'): Number(47),
                               Length('Source'): Number(48),
                               First('Source'): Number(48),
                               Last('Source'): Number(95),
                               Length('TPID'): Number(16),
                               First('TPID'): Number(96),
                               Last('TPID'): Number(111),
                               Length('EtherType'): Number(16),
                               First('EtherType'): Number(96),
                               Last('EtherType'): Number(111),
                               Length('Payload'): Add(Last('Message'), Number(-111)),
                               First('Payload'): Number(112),
                               Last('Payload'): Last('Message')
                           })
                   }))
        ])

        self.assertEqual(ETHERNET_PDU.fields(), expected)
Пример #30
0
def message_structure_invariant(
    message: Message, prefix: str, link: Link = None, embedded: bool = False
) -> Expr:
    def prefixed(name: str) -> Expr:
        return Selected(Variable("Ctx"), name) if not embedded else Variable(name)

    if not link:
        return message_structure_invariant(message, prefix, message.outgoing(INITIAL)[0], embedded)

    source = link.source
    target = link.target

    if target is FINAL:
        return TRUE

    field_type = message.types[target]
    condition = link.condition.substituted(substitution(message, embedded)).simplified()
    length = (
        Size(prefix * full_base_type_name(field_type))
        if isinstance(field_type, Scalar)
        else link.length.substituted(
            substitution(message, embedded, target_type=const.TYPES_BIT_LENGTH)
        ).simplified()
    )
    first = (
        prefixed("First")
        if source == INITIAL
        else link.first.substituted(substitution(message, embedded))
        .substituted(
            mapping={
                UNDEFINED: Add(
                    Selected(Indexed(prefixed("Cursors"), Variable(source.affixed_name)), "Last"),
                    Number(1),
                )
            }
        )
        .simplified()
    )

    return If(
        [
            (
                AndThen(
                    Call(
                        "Structural_Valid",
                        [Indexed(prefixed("Cursors"), Variable(target.affixed_name))],
                    ),
                    condition,
                ),
                AndThen(
                    Equal(
                        Add(
                            Sub(
                                Selected(
                                    Indexed(prefixed("Cursors"), Variable(target.affixed_name)),
                                    "Last",
                                ),
                                Selected(
                                    Indexed(prefixed("Cursors"), Variable(target.affixed_name)),
                                    "First",
                                ),
                            ),
                            Number(1),
                        ),
                        length,
                    ),
                    Equal(
                        Selected(
                            Indexed(prefixed("Cursors"), Variable(target.affixed_name)),
                            "Predecessor",
                        ),
                        Variable(source.affixed_name),
                    ),
                    Equal(
                        Selected(
                            Indexed(prefixed("Cursors"), Variable(target.affixed_name)), "First"
                        ),
                        first,
                    ),
                    *[
                        message_structure_invariant(message, prefix, l, embedded)
                        for l in message.outgoing(target)
                    ],
                ),
            )
        ]
    ).simplified()