Skip to content

Commit 0d7b148

Browse files
authored
Checks added to PcapNg processing (#4373)
* Check added to PcapNg processing * Unit tests
1 parent 8cea357 commit 0d7b148

File tree

2 files changed

+50
-11
lines changed

2 files changed

+50
-11
lines changed

scapy/utils.py

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,9 +1603,14 @@ def _read_block(self, size=MTU):
16031603
warning("PcapNg: Error reading blocklen before block body")
16041604
raise EOFError
16051605
if blocklen < 12:
1606-
warning("Invalid block length !")
1606+
warning("PcapNg: Invalid block length !")
16071607
raise EOFError
1608-
block = self.f.read(blocklen - 12)
1608+
1609+
_block_body_length = blocklen - 12
1610+
block = self.f.read(_block_body_length)
1611+
if len(block) != _block_body_length:
1612+
raise Scapy_Exception("PcapNg: Invalid Block body length "
1613+
"(too short)")
16091614
self._read_block_tail(blocklen)
16101615
if blocktype in self.blocktypes:
16111616
return self.blocktypes[blocktype](block, size)
@@ -1635,25 +1640,41 @@ def _read_block_shb(self):
16351640
elif endian == b"\x4d\x3c\x2b\x1a":
16361641
self.endian = "<"
16371642
else:
1638-
warning("Bad magic in Section Header block (not a pcapng file?)")
1643+
warning("PcapNg: Bad magic in Section Header Block"
1644+
" (not a pcapng file?)")
16391645
raise EOFError
16401646

1641-
blocklen = struct.unpack(self.endian + "I", _blocklen)[0]
1647+
try:
1648+
blocklen = struct.unpack(self.endian + "I", _blocklen)[0]
1649+
except struct.error:
1650+
warning("PcapNg: Could not read blocklen")
1651+
raise EOFError
16421652
if blocklen < 28:
1643-
warning(f"Invalid SHB block length ({blocklen})!")
1653+
warning(f"PcapNg: Invalid Section Header Block length ({blocklen})!") # noqa: E501
16441654
raise EOFError
16451655

16461656
# Major version must be 1
16471657
_major = self.f.read(2)
1648-
major = struct.unpack(self.endian + "H", _major)[0]
1658+
try:
1659+
major = struct.unpack(self.endian + "H", _major)[0]
1660+
except struct.error:
1661+
warning("PcapNg: Could not read major value")
1662+
raise EOFError
16491663
if major != 1:
1650-
warning(f"SHB Major version {major} unsupported !")
1664+
warning(f"PcapNg: SHB Major version {major} unsupported !")
16511665
raise EOFError
16521666

16531667
# Skip minor version & section length
1654-
self.f.read(10)
1668+
skipped = self.f.read(10)
1669+
if len(skipped) != 10:
1670+
warning("PcapNg: Could not read minor value & section length")
1671+
raise EOFError
16551672

1656-
options = self.f.read(blocklen - 28)
1673+
_options_len = blocklen - 28
1674+
options = self.f.read(_options_len)
1675+
if len(options) != _options_len:
1676+
raise Scapy_Exception("PcapNg: Invalid Section Header Block "
1677+
" options (too short)")
16571678
self._read_block_tail(blocklen)
16581679
self._read_options(options)
16591680

@@ -1673,7 +1694,12 @@ def _read_options(self, options):
16731694
# type: (bytes) -> Dict[int, bytes]
16741695
opts = dict()
16751696
while len(options) >= 4:
1676-
code, length = struct.unpack(self.endian + "HH", options[:4])
1697+
try:
1698+
code, length = struct.unpack(self.endian + "HH", options[:4])
1699+
except struct.error:
1700+
warning("PcapNg: options header is too small "
1701+
"%d !" % len(options))
1702+
raise EOFError
16771703
if code != 0 and 4 + length < len(options):
16781704
opts[code] = options[4:4 + length]
16791705
if code == 0:
@@ -1910,7 +1936,7 @@ def read_packet(self, size=MTU, **kwargs):
19101936
p.comment = comment
19111937
p.direction = direction
19121938
if ifname is not None:
1913-
p.sniffed_on = ifname.decode('utf-8')
1939+
p.sniffed_on = ifname.decode('utf-8', 'backslashreplace')
19141940
return p
19151941

19161942
def recv(self, size: int = MTU, **kwargs: Any) -> 'Packet': # type: ignore

test/regression.uts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,6 +2252,19 @@ for i in range(len(plist)):
22522252
assert type(plist_check[i]) == type(plist[0])
22532253
assert bytes(plist_check[i]) == bytes(plist[i])
22542254

2255+
= OSS-Fuzz Findings
2256+
2257+
from io import BytesIO
2258+
# Issue 68352
2259+
file = BytesIO(b"\n\r\r\n\x1c\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x1c\x00\x00\x00\x01\x00\x00\x00\x14\x00\x00\x00\xe4\x00\x00\x00\x00\x00\x04\x00\x14\x00\x00\x00\x01\x00\x00\x00(\x00\x00\x00\xe4\x00\x00\x00\x00\x00\x04\x00\x02\x00\t\x00b'ens16\xb0'\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x06\x00\x00\x004\x00\x00\x00\x01\x00\x00\x00}\x17\x06\x00\xb5t\x1d\x85\x14\x00\x00\x00\x14\x00\x00\x00E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x014\x00\x00\x00")
2260+
rdpcap(file)
2261+
# Issue 68354
2262+
file = BytesIO(b'\n\r\r\n\xff\xfe\xfe\xffM<+\x1a')
2263+
try:
2264+
rdpcap(file)
2265+
except Scapy_Exception:
2266+
pass
2267+
22552268
= Read a pcap file with wirelen != captured len
22562269
pktpcapwirelen = rdpcap(pcapwirelenfile)
22572270

0 commit comments

Comments
 (0)