Skip to content

Oddities with FieldListField #1661

@LRGH

Description

@LRGH

I have been looking at the internals of FieldListField and would like to suggest some simple changes.

  • Looking at FieldListField.getfield, we see that the "internal" representation of this field is a list of internal representations of each element. Therefore the function FieldListField.i2m is erroneous: it does not convert the "internal" representation in "machine" representation.
  • The semantics of addfield is that it expects an "internal" representation. Therefore in FieldListField.addfield the line val = self.i2m(pkt, val) can be removed. We should't need to deal with the case where val is None, because it is an invalid "internal" representation, and having None as the default value is already managed in __init__.

I also would like to suggest a much more complex change: let's take for example the following piece of code:

class X(Packet):
    fields_desc = [ FieldListField("f", [], ByteField("",0)) ]
m = X()
m.f.append(3)
m.show()
assert(repr(m) == "<X  |>")
assert(raw(m) == b"\x03")
assert(m.default_fields == {'f': [3]})
assert(m.fields == {})

This is an odd behaviour, because in this case m.f is m.default_fields['f'] which should not be changed by simple operations. A workaround is to do m.f = m.f before modifying m.f but this is not intuitive.

  • First proposal: we can note that m.f is the "human" representation of the field list, and therefore there is no reason that changing this value should change the content of the packet. Therefore we define FieldListField.i2h = lambda self, pkt, x: list(x). By making a copy we make sure that modifications of m.f have no impact on m (this breaks some non-regression tests). We can even define FieldListField.i2h = lambda self, pkt, x: tuple(x) to make it immutable, but it will break more non-regression tests.
  • Second proposal: use some other type than list for the "human" representation, to allow modifications of m.f with a sound behaviour. I have begun to work on such an implementation, and I am wondering if others are interested. I prefer this approach because I like when scapy is doing magic, and I can extend this approach to an implementation of HTTP where p.headers['Content-Type'] can be used to read or write a specific header...

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions