def test_mul_simplified(self) -> None: self.assertEqual( Mul(Value('X'), Number(2)).simplified(), Mul(Value('X'), Number(2))) self.assertEqual(Mul(Value('X'), Number(1)).simplified(), Value('X')) self.assertEqual( Mul(Number(2), Number(3), Number(5)).simplified(), Number(30))
def test_mul(self) -> None: self.assertEqual( Mul(Number(6), Number(4)).z3expr(), z3.IntVal(6) * z3.IntVal(4)) self.assertEqual( Mul(Number(2), Number(4), Number(8)).z3expr(), z3.IntVal(2) * z3.IntVal(4) * z3.IntVal(8), )
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))))
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"), )
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]
def test_array_type_spec() -> None: spec = { "Array_Type": Specification( ContextSpec([]), PackageSpec( "Array_Type", [ ModularInteger("__PACKAGE__.Byte", Number(256)), ArraySpec("__PACKAGE__.Bytes", ReferenceSpec("__PACKAGE__.Byte")), MessageSpec( "__PACKAGE__.Foo", [ Component( "Length", "Byte", [Then("Bytes", UNDEFINED, Mul(Variable("Length"), Number(8)))], ), Component("Bytes", "Bytes"), ], ), ArraySpec("__PACKAGE__.Bar", ReferenceSpec("__PACKAGE__.Foo")), ], ), ) } assert_specifications_files([f"{TESTDIR}/array_type.rflx"], spec)
def create_tlv_message() -> Message: tag_type = Enumeration("TLV.Tag", { "Msg_Data": Number(1), "Msg_Error": Number(3) }, Number(2), False) length_type = ModularInteger("TLV.Length", Pow(Number(2), Number(14))) structure = [ Link(INITIAL, Field("Tag")), Link(Field("Tag"), Field("Length"), Equal(Variable("Tag"), Variable("Msg_Data"))), Link(Field("Tag"), FINAL, Equal(Variable("Tag"), Variable("Msg_Error"))), Link(Field("Length"), Field("Value"), length=Mul(Variable("Length"), Number(8))), Link(Field("Value"), FINAL), ] types = { Field("Tag"): tag_type, Field("Length"): length_type, Field("Value"): Payload() } return Message("TLV.Message", structure, types)
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"), )
def create_array_message() -> Message: length_type = ModularInteger("Arrays.Length", Pow(Number(2), Number(8))) modular_type = ModularInteger("Arrays.Modular_Integer", Pow(Number(2), Number(16))) modular_vector_type = Array("Arrays.Modular_Vector", modular_type) range_type = RangeInteger("Arrays.Range_Integer", Number(1), Number(100), Number(8)) range_vector_type = Array("Arrays.Range_Vector", range_type) enum_type = Enumeration( "Arrays.Enumeration", { "ZERO": Number(0), "ONE": Number(1), "TWO": Number(2) }, Number(8), False, ) enum_vector_type = Array("Arrays.Enumeration_Vector", enum_type) av_enum_type = Enumeration( "Arrays.AV_Enumeration", { "AV_ZERO": Number(0), "AV_ONE": Number(1), "AV_TWO": Number(2) }, Number(8), True, ) av_enum_vector_type = Array("Arrays.AV_Enumeration_Vector", av_enum_type) structure = [ Link(INITIAL, Field("Length")), Link(Field("Length"), Field("Modular_Vector"), length=Mul(Variable("Length"), Number(8))), Link(Field("Modular_Vector"), Field("Range_Vector"), length=Number(16)), Link(Field("Range_Vector"), Field("Enumeration_Vector"), length=Number(16)), Link(Field("Enumeration_Vector"), Field("AV_Enumeration_Vector"), length=Number(16)), Link(Field("AV_Enumeration_Vector"), FINAL), ] types = { Field("Length"): length_type, Field("Modular_Vector"): modular_vector_type, Field("Range_Vector"): range_vector_type, Field("Enumeration_Vector"): enum_vector_type, Field("AV_Enumeration_Vector"): av_enum_vector_type, } return Message("Arrays.Message", structure, types)
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")], )
def test_message_in_message() -> None: length = ModularInteger("Message_In_Message.Length", Pow(Number(2), Number(16))) length_value = Message( "Message_In_Message.Length_Value", [ Link(INITIAL, Field("Length")), Link(Field("Length"), Field("Value"), length=Mul(Number(8), Variable("Length"))), Link(Field("Value"), FINAL), ], {Field("Length"): length, Field("Value"): Opaque()}, ) derived_length_value = DerivedMessage("Message_In_Message.Derived_Length_Value", length_value) message = Message( "Message_In_Message.Message", [ Link(INITIAL, Field("Foo_Length")), Link(Field("Foo_Value"), Field("Bar_Length")), Link(Field("Bar_Value"), FINAL), Link( Field("Foo_Length"), Field("Foo_Value"), length=Mul(Variable("Foo_Length"), Number(8)), ), Link( Field("Bar_Length"), Field("Bar_Value"), length=Mul(Variable("Bar_Length"), Number(8)), ), ], { Field("Foo_Length"): length, Field("Foo_Value"): Opaque(), Field("Bar_Length"): length, Field("Bar_Value"): Opaque(), }, ) derived_message = DerivedMessage("Message_In_Message.Derived_Message", message) assert_messages_files( [f"{TESTDIR}/message_in_message.rflx"], [length_value, derived_length_value, message, derived_message], )
def test_tlv_message_with_not_operator_exhausting() -> None: message = Message( "TLV::Message_With_Not_Operator_Exhausting", [ Link(INITIAL, Field("Tag")), Link( Field("Tag"), Field("Length"), Not(Not(Not(NotEqual(Variable("Tag"), Variable("Msg_Data"))))), ), Link( Field("Tag"), FINAL, reduce( lambda acc, f: f(acc), [Not, Not] * 16, Not( Or( Not( Not( Equal(Variable("Tag"), Variable("Msg_Data")))), Not(Equal(Variable("Tag"), Variable("Msg_Error"))), )), ), ), Link(Field("Length"), Field("Value"), size=Mul(Variable("Length"), Number(8))), Link(Field("Value"), FINAL), ], { Field("Tag"): TLV_TAG, Field("Length"): TLV_LENGTH, Field("Value"): OPAQUE }, ) with pytest.raises( FatalError, match=re.escape( "failed to simplify complex expression `not (not (not (not " "(not (not (not (not (not (not (not (not (not (not (not (not " "(not (not (not (not (not (not (not (not (not (not (not (not " "(not (not (not (not (not (not (not (Tag = TLV::Msg_Data))\n" " " "or not (Tag = TLV::Msg_Error))))))))))))))))))))))))))))))))))` " "after `16` iterations, best effort: " "`not (not (not (not (not (not (not (not (not (not (not (not (not " "(not (not (not (not (Tag = TLV::Msg_Data\n" " or Tag /= TLV::Msg_Error)))))))))))))))))`"), ): model = PyRFLX(model=Model([TLV_TAG, TLV_LENGTH, message])) pkg = model.package("TLV") msg = pkg.new_message("Message_With_Not_Operator_Exhausting") test_bytes = b"\x01\x00\x04\x00\x00\x00\x00" msg.parse(test_bytes)
def test_valid_length_reference() -> None: structure = [ Link(INITIAL, Field("F1")), Link(Field("F1"), Field("F2"), length=Mul(Number(8), Variable("F1"))), Link(Field("F2"), FINAL), ] types = { Field("F1"): MODULAR_INTEGER, Field("F2"): Opaque(), } Message("P.M", structure, types)
def test_ass_expr_substituted() -> None: assert_equal( And(Equal(Variable("X"), Number(1)), Variable("Y")).substituted( lambda x: Variable(f"P_{x}") if isinstance(x, Variable) else x ), And(Equal(Variable("P_X"), Number(1)), Variable("P_Y")), ) assert_equal( Mul(Variable("X"), Number(1)).substituted( lambda x: Variable("Y") if x == Mul(Variable("X"), Number(1)) else x ), Variable("Y"), ) assert_equal( And(Equal(Variable("X"), Number(1)), Variable("Y")).substituted( lambda x: Variable(f"P_{x}") if isinstance(x, Variable) else (Or(*x.terms) if isinstance(x, And) else x) ), Or(Equal(Variable("P_X"), Number(1)), Variable("P_Y")), )
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))), )
def create_array_inner_message() -> Message: length_type = ModularInteger("Arrays.Length", Pow(Number(2), Number(8))) structure = [ Link(INITIAL, Field("Length")), Link(Field("Length"), Field("Payload"), length=Mul(Variable("Length"), Number(8))), Link(Field("Payload"), FINAL), ] types = {Field("Length"): length_type, Field("Payload"): Payload()} return Message("Arrays.Inner_Message", structure, types)
def test_opaque_valid_byte_aligned_dynamic_mul() -> None: Message( "P.M", [ Link(INITIAL, Field("L")), Link(Field("L"), Field("O1"), length=Mul(Number(8), Variable("L"))), Link(Field("O1"), FINAL), ], { Field("L"): MODULAR_INTEGER, Field("O1"): Opaque() }, )
def create_array_messages_message() -> Message: structure = [ Link(INITIAL, Field("Length")), Link(Field("Length"), Field("Messages"), length=Mul(Variable("Length"), Number(8))), Link(Field("Messages"), FINAL), ] types = { Field("Length"): ModularInteger("Arrays.Length", Pow(Number(2), Number(8))), Field("Messages"): Array("Arrays.Inner_Messages", Reference("Arrays.Inner_Message")), } return Message("Arrays.Messages_Message", structure, types)
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[)]$', )
def test_tlv_message_with_not_operator() -> None: message = Message( "TLV::Message_With_Not_Operator", [ Link(INITIAL, Field("Tag")), Link( Field("Tag"), Field("Length"), Not(Not(Not(NotEqual(Variable("Tag"), Variable("Msg_Data"))))), ), Link( Field("Tag"), FINAL, Not( Not( Not( Or( Not( Not( Equal(Variable("Tag"), Variable("Msg_Data")))), Not( Equal(Variable("Tag"), Variable("Msg_Error"))), )))), ), Link(Field("Length"), Field("Value"), size=Mul(Variable("Length"), Number(8))), Link(Field("Value"), FINAL), ], { Field("Tag"): TLV_TAG, Field("Length"): TLV_LENGTH, Field("Value"): OPAQUE }, ) model = PyRFLX(model=Model([TLV_TAG, TLV_LENGTH, message])) pkg = model.package("TLV") msg = pkg.new_message("Message_With_Not_Operator") test_bytes = b"\x01\x00\x04\x00\x00\x00\x00" msg.parse(test_bytes) assert msg.valid_message assert msg.bytestring == test_bytes
def test_tlv_valid_enum() -> None: structure = [ Link(INITIAL, Field("L")), Link(Field("L"), Field("T")), Link( Field("T"), Field("V"), length=Mul(Number(8), Variable("L")), condition=And(NotEqual(Variable("T"), Variable("TWO")), LessEqual(Variable("L"), Number(8192))), ), Link(Field("V"), FINAL), ] types = { Field("L"): RANGE_INTEGER, Field("T"): ENUMERATION, Field("V"): Opaque(), } Message("P.M", structure, types)
def test_aggregate_equal_invalid_length_field() -> None: length = Field(ID("Length", Location((2, 5)))) magic = Field(ID("Magic", Location((3, 5)))) structure = [ Link(INITIAL, length), Link(length, magic, length=Mul(Number(8), Variable("Length"), location=Location((6, 5)))), Link( magic, FINAL, condition=Equal(Variable("Magic"), Aggregate(Number(1), Number(2)), location=Location((10, 5))), ), ] types = { Field("Length"): RangeInteger("P.Length_Type", Number(10), Number(100), Number(8), Location((5, 10))), Field(ID("Magic", Location((17, 3)))): Opaque(), } assert_message_model_error( structure, types, r"^" r'<stdin>:10:5: model: error: contradicting condition in "P.M"\n' r'<stdin>:2:5: model: info: on path: "Length"\n' r'<stdin>:3:5: model: info: on path: "Magic"\n' r'<stdin>:6:5: model: info: unsatisfied "Magic\'Length = 8 [*] Length"\n' r'<stdin>:10:5: model: info: unsatisfied "2 [*] 8 = Magic\'Length"\n' r'<stdin>:5:10: model: info: unsatisfied "Length >= 10"' r"$", )
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]
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]
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)
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)
) NULL_MESSAGE = Message("Null::Message", [], {}, skip_proof=True) NULL_MODEL = Model([NULL_MESSAGE]) TLV_TAG = Enumeration( "TLV::Tag", [("Msg_Data", Number(1)), ("Msg_Error", Number(3))], Number(8), always_valid=False ) TLV_LENGTH = ModularInteger("TLV::Length", Pow(Number(2), Number(16))) TLV_MESSAGE = Message( "TLV::Message", [ Link(INITIAL, Field("Tag")), Link(Field("Tag"), Field("Length"), Equal(Variable("Tag"), Variable("Msg_Data"))), Link(Field("Tag"), FINAL, Equal(Variable("Tag"), Variable("Msg_Error"))), Link(Field("Length"), Field("Value"), size=Mul(Variable("Length"), Number(8))), Link(Field("Value"), FINAL), ], {Field("Tag"): TLV_TAG, Field("Length"): TLV_LENGTH, Field("Value"): OPAQUE}, skip_proof=True, ) TLV_MODEL = Model([TLV_TAG, TLV_LENGTH, TLV_MESSAGE]) TLV_MESSAGES = Sequence("TLV::Messages", TLV_MESSAGE) TLV_TAGS = Sequence("TLV::Tags", TLV_TAG) TLV_WITH_CHECKSUM_TAG = Enumeration( "TLV_With_Checksum::Tag", [("Msg_Data", Number(1)), ("Msg_Error", Number(3))], Number(8), always_valid=False,
def test_mul() -> None: assert Mul(Number(6), Number(4)).z3expr() == z3.IntVal(6) * z3.IntVal(4) assert_equal( Mul(Number(2), Number(4), Number(8)).z3expr(), z3.IntVal(2) * z3.IntVal(4) * z3.IntVal(8) )
def __process_pdus(self, pdus: List[PDU]) -> None: seen_types: List[str] = [] for pdu in pdus: if pdu.package not in self.__units: self.__units[pdu.package] = Unit(COMMON_CONTEXT, Package(pdu.package, [], [])) context: List[ContextItem] = [] package = Package(pdu.full_name, [], []) self.__units[pdu.full_name] = Unit(context, package) package.subprograms.extend(contain_functions()) facts: Dict[Attribute, MathExpr] = { First('Message'): Mul(First('Buffer'), Number(8)), Last('Message'): Mul(Last('Buffer'), Number(8)), Length('Message'): Sub(Add(Mul(Last('Buffer'), Number(8)), Number(8)), Mul(First('Buffer'), Number(8))) } fields = pdu.fields(facts, First('Buffer')) self.__pdu_fields[pdu.full_name] = list(fields.keys()) for field in fields.values(): if field.name == 'FINAL': continue if f'{pdu.package}.{field.type.name}' not in seen_types: seen_types.append(f'{pdu.package}.{field.type.name}') self.__create_type(field.type, pdu.package) if isinstance(field.type, Array) and 'Payload' not in field.type.name: with_clause = WithClause( [f'{pdu.package}.{field.type.name}']) if with_clause not in context: context.append(with_clause) for variant_id, variant in field.variants.items(): package.subprograms.append( variant_validation_function(field, variant_id, variant)) package.subprograms.extend( variant_accessor_functions(field, variant_id, variant)) package.subprograms.append(field_validation_function(field)) package.subprograms.extend( field_accessor_functions(field, pdu.package)) package.subprograms.append( message_validation_function( list(fields['FINAL'].variants.values()))) package.subprograms.append( message_length_function(list( fields['FINAL'].variants.values()))) self.__create_unreachable_functions(pdus)
def test_term_to_bytes(self) -> None: self.assertEqual( Add(Mul(Number(8), Number(48)), Sub(Value('X'), Number(80)), Div(Number(8), Number(24))).to_bytes(), Add(Mul(Number(1), Number(6)), Sub(Value('X'), Number(10)), Div(Number(1), Number(3))))