Skip to content

Commit 35877da

Browse files
Restore default clear_cache() behaviour (secdev#4707)
- `upwards` (`False` by default) and `downwards` (`True` by default) parameters added to `clear_cache()`. - Set to `upwards=True` and `downwards=False` in `setfieldval()`, `delfieldval()`, `add_payload()` and `remove_payload()`. - Former implementation restored for `downwards=True`.
1 parent debbbde commit 35877da

File tree

1 file changed

+27
-27
lines changed

1 file changed

+27
-27
lines changed

scapy/packet.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ def add_payload(self, payload, clear_cache=True):
400400

401401
# Invalidate cache when the packet has changed.
402402
if clear_cache:
403-
self.clear_cache()
403+
self.clear_cache(upwards=True, downwards=False)
404404

405405
def remove_payload(self):
406406
# type: () -> None
@@ -409,7 +409,7 @@ def remove_payload(self):
409409
self.overloaded_fields = {}
410410

411411
# Invalidate cache when the packet has changed.
412-
self.clear_cache()
412+
self.clear_cache(upwards=True, downwards=False)
413413

414414
def add_underlayer(self, underlayer):
415415
# type: (Packet) -> None
@@ -655,7 +655,7 @@ def setfieldval(self, attr, val):
655655
any2i(self, val)
656656
self.explicit = 0
657657
# Invalidate cache when the packet has changed.
658-
self.clear_cache()
658+
self.clear_cache(upwards=True, downwards=False)
659659
self.wirelen = None
660660
elif attr == "payload":
661661
self.remove_payload()
@@ -679,7 +679,7 @@ def delfieldval(self, attr):
679679
del self.fields[attr]
680680
self.explicit = 0 # in case a default value must be explicit
681681
# Invalidate cache when the packet has changed.
682-
self.clear_cache()
682+
self.clear_cache(upwards=True, downwards=False)
683683
self.wirelen = None
684684
elif attr in self.default_fields:
685685
pass
@@ -810,33 +810,33 @@ def copy_field_value(self, fieldname, value):
810810
# type: (str, Any) -> Any
811811
return self.get_field(fieldname).do_copy(value)
812812

813-
def clear_cache(self):
814-
# type: () -> None
813+
def clear_cache(self, upwards=False, downwards=True):
814+
# type: (bool, bool) -> None
815815
"""
816-
Ensure cache invalidation for all:
817-
818-
- parent packet if any,
819-
- underlayer if any.
816+
Clear the raw packet cache for the current packet.
820817
821-
.. note::
822-
Contrary to base former implementation, don't invalidate cache for:
818+
``upwards`` and ``downwards`` indicate how this call should recurse in the packet tree.
823819
824-
- packet fields if any,
825-
- payload if any.
826-
827-
.. todo::
828-
Shall we restore a default behaviour to avoid breaking the API:
829-
"Clear the raw packet cache for the field and all its subfields"?
820+
:param upwards: Set to ``True`` to clear cache recursively over parent and underlayer packets. ``False`` by default.
821+
:param downwards: Set to ``True`` (default) to clear cache recursively over subfields and payload.
830822
"""
831-
def _clear_cache_ascending(pkt): # type: (Packet) -> None
832-
pkt.raw_packet_cache = None
833-
834-
if isinstance(pkt, Packet) and pkt.parent:
835-
_clear_cache_ascending(pkt.parent)
836-
if pkt.underlayer:
837-
_clear_cache_ascending(pkt.underlayer)
838-
839-
_clear_cache_ascending(self)
823+
self.raw_packet_cache = None
824+
825+
if upwards:
826+
if self.parent:
827+
self.parent.clear_cache(upwards=True, downwards=False)
828+
if self.underlayer:
829+
self.underlayer.clear_cache(upwards=True, downwards=False)
830+
if downwards:
831+
for fname, fval in self.fields.items():
832+
fld = self.get_field(fname)
833+
if fld.holds_packets:
834+
if isinstance(fval, Packet):
835+
fval.clear_cache(upwards=False, downwards=True)
836+
elif isinstance(fval, list):
837+
for fsubval in fval:
838+
fsubval.clear_cache(upwards=False, downwards=True)
839+
self.payload.clear_cache(upwards=False, downwards=True)
840840

841841
def self_build(self):
842842
# type: () -> bytes

0 commit comments

Comments
 (0)