diff --git a/scapy/fields.py b/scapy/fields.py index 23c8fa774c3..b5fde672e8a 100644 --- a/scapy/fields.py +++ b/scapy/fields.py @@ -312,6 +312,30 @@ class _FieldContainer(object): """ __slots__ = ["fld"] + def copy(self): + # type: () -> Any + other = self.__class__.__new__(self.__class__) + for slot in self.__slots__: + val = object.__getattribute__(self, slot) + if hasattr(val, "copy"): + val = val.copy() + object.__setattr__(other, slot, val) + return other + + def __setattr__(self, attr, value): + # type: (str, Any) -> None + try: + object.__setattr__(self, attr, value) + except AttributeError as ex: + for cls in type(self).__mro__: + if attr in cls.__dict__: + raise ex + try: + fld = object.__getattribute__(self, "fld") + except AttributeError: + raise ex + setattr(fld, attr, value) + def __getattr__(self, attr): # type: (str) -> Any return getattr(self.fld, attr) diff --git a/test/fields.uts b/test/fields.uts index 38263f2a49f..a127056a1aa 100644 --- a/test/fields.uts +++ b/test/fields.uts @@ -15,6 +15,34 @@ #Field("foo", None, fmt="I").getfield(None, b"\x12\x34\x56\x78ABCD") #assert _ == ("ABCD",0x12345678) += FieldContainer copy +~ core field + +field_container = Emph(ByteField("foo", 0)) +field_container_copy = field_container.copy() + +assert type(field_container_copy) is Emph +assert type(field_container_copy.fld) is ByteField +assert field_container_copy.fld is not field_container.fld +assert field_container_copy.name == "foo" +assert field_container_copy.default == 0 + +class TEST_FIELD_CONTAINER_COPY_SOURCE(Packet): + fields_desc = [Emph(ByteField("foo", 0))] + +class TEST_FIELD_CONTAINER_COPY_TARGET(Packet): + fields_desc = [TEST_FIELD_CONTAINER_COPY_SOURCE, ByteField("bar", 0)] + foo = 7 + +source_field = TEST_FIELD_CONTAINER_COPY_SOURCE.fields_desc[0] +target_field = TEST_FIELD_CONTAINER_COPY_TARGET.fields_desc[0] + +assert type(target_field) is Emph +assert type(target_field.fld) is ByteField +assert target_field.fld is not source_field.fld +assert target_field.default == 7 +assert source_field.default == 0 + = ConditionnalField class ~ core field