Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scapy/contrib/ibeacon.uts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ assert d == d2

= iBeacon (encode LE Set Advertising Data)

d = hex_bytes('1E0201021AFF4C000215FB0B57A2822844CD913A94A122BA120600010002D100')
d = hex_bytes('1E0201061AFF4C000215FB0B57A2822844CD913A94A122BA120600010002D100')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was triggered by the FlagsField bug

p = Apple_BLE_Submessage()/IBeacon_Data(
uuid='fb0b57a2-8228-44cd-913a-94a122ba1206',
major=1, minor=2, tx_power=-47)
Expand Down
12 changes: 5 additions & 7 deletions scapy/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -1971,13 +1971,11 @@ def _fixup_val(self, x):
used in *2i() and i2*() methods.

"""
if isinstance(x, (list, tuple)):
return type(x)(
v if v is None or isinstance(v, FlagValue)
else FlagValue(v, self.names)
for v in x
)
return x if x is None or isinstance(x, FlagValue) else FlagValue(x, self.names) # noqa: E501
if isinstance(x, FlagValue):
return x
if x is None:
return None
return FlagValue(x, self.names)

def any2i(self, pkt, x):
return self._fixup_val(super(FlagsField, self).any2i(pkt, x))
Expand Down
51 changes: 37 additions & 14 deletions scapy/packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,12 @@ def do_init_cached_fields(self):

# Deepcopy default references
for fname in Packet.class_default_fields_ref[cls_name]:
value = copy.deepcopy(self.default_fields[fname])
setattr(self, fname, value)
value = self.default_fields[fname]
try:
self.fields[fname] = value.copy()
except AttributeError:
# Python 2.7 - list only
self.fields[fname] = value[:]

def prepare_cached_fields(self, flist):
"""
Expand Down Expand Up @@ -435,8 +439,13 @@ def __repr__(self):
repr(self.payload),
ct.punct(">"))

def __str__(self):
return str(self.build())
if six.PY2:
def __str__(self):
return self.build()
else:
def __str__(self):
warning("Calling str(pkt) on Python 3 makes no sense!")
return str(self.build())

def __bytes__(self):
return self.build()
Expand Down Expand Up @@ -488,9 +497,14 @@ def copy_fields_dict(self, fields):
def clear_cache(self):
"""Clear the raw packet cache for the field and all its subfields"""
self.raw_packet_cache = None
for _, fval in six.iteritems(self.fields):
if isinstance(fval, Packet):
fval.clear_cache()
for fld, fval in six.iteritems(self.fields):
fld = self.get_field(fld)
if fld.holds_packets:
if isinstance(fval, Packet):
fval.clear_cache()
elif isinstance(fval, list):
for fsubval in fval:
fsubval.clear_cache()
self.payload.clear_cache()

def self_build(self, field_pos_list=None):
Expand Down Expand Up @@ -838,9 +852,12 @@ def guess_payload_class(self, payload):
"""
for t in self.aliastypes:
for fval, cls in t.payload_guess:
if all(hasattr(self, k) and v == self.getfieldval(k)
for k, v in six.iteritems(fval)):
return cls
try:
if all(v == self.getfieldval(k)
for k, v in six.iteritems(fval)):
return cls
except AttributeError:
pass
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually quite a big improvement: in fact hasattr calls __getattr__ under the hood, which calls getfieldval => we actually did getfieldval twice each time.

return self.default_payload_class(payload)

def default_payload_class(self, payload):
Expand Down Expand Up @@ -924,19 +941,25 @@ def __iterlen__(self):
six.iteritems(self.overloaded_fields))
if isinstance(val, VolatileValue)] + list(self.fields)
length = 1

def is_valid_gen_tuple(x):
if not isinstance(x, tuple):
return False
return len(x) == 2 and all(isinstance(z, int) for z in x)

for field in fields:
fld, val = self.getfield_and_val(field)
if hasattr(val, "__iterlen__"):
length *= val.__iterlen__()
elif isinstance(val, tuple) and len(val) == 2 and all(hasattr(z, "__int__") for z in val): # noqa: E501
length *= (val[1] - val[0])
elif is_valid_gen_tuple(val):
length *= (val[1] - val[0] + 1)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason I missed that: (0, 5) makes 6 values... -_-

elif isinstance(val, list) and not fld.islist:
len2 = 0
for x in val:
if hasattr(x, "__iterlen__"):
len2 += x.__iterlen__()
elif isinstance(x, tuple) and len(x) == 2 and all(hasattr(z, "__int__") for z in x): # noqa: E501
len2 += (x[1] - x[0])
elif is_valid_gen_tuple(x):
len2 += (x[1] - x[0] + 1)
elif isinstance(x, list):
len2 += len(x)
else:
Expand Down
4 changes: 4 additions & 0 deletions scapy/volatile.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"""

from __future__ import absolute_import
import copy
import random
import time
import math
Expand Down Expand Up @@ -104,6 +105,9 @@ def __bytes__(self):
def __len__(self):
return len(self._fix())

def copy(self):
return copy.copy(self)

def _fix(self):
return None

Expand Down
9 changes: 0 additions & 9 deletions test/regression.uts
Original file line number Diff line number Diff line change
Expand Up @@ -10706,15 +10706,6 @@ assert not any(getattr(p1.flags | p2.flags, f) for f in 'FRPECN')
assert TCP(flags="SA").flags & TCP(flags="S").flags == TCP(flags="S").flags
assert TCP(flags="SA").flags | TCP(flags="S").flags == TCP(flags="SA").flags

= Using tuples and lists as flag values
~ IP TCP

plist = PacketList(list(IP()/TCP(flags=(0, 2**9 - 1))))
assert [p[TCP].flags for p in plist] == [x for x in range(512)]

plist = PacketList(list(IP()/TCP(flags=["S", "SA", "A"])))
assert [p[TCP].flags for p in plist] == [2, 18, 16]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also made very little sense: it abuses the bugs in __iter__ to generate a list of packets, whereas it should only have been a flag field.


############
############
Expand Down