From f90e246c8d45086919ed9cfea39f16ccb4d00058 Mon Sep 17 00:00:00 2001 From: Guillaume Valadon Date: Thu, 1 Oct 2026 14:49:56 -0700 Subject: [PATCH] Handle corrupted gzip streams in pcap/pcapng readers AI-Assisted: yes (GLM-5.3) --- scapy/utils.py | 15 ++++++++++++--- test/regression.uts | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/scapy/utils.py b/scapy/utils.py index eb303aac374..4cfef59d438 100644 --- a/scapy/utils.py +++ b/scapy/utils.py @@ -1453,7 +1453,11 @@ def __init__(self, filename, fdesc=None, magic=None): # type: ignore raise Scapy_Exception( "Not a pcap capture file (bad magic: %r)" % magic ) - hdr = self.f.read(20) + try: + hdr = self.f.read(20) + except (OSError, OverflowError, zlib.error) as e: + warning(f"Pcap: {e}") + raise Scapy_Exception("Invalid pcap file (corrupted stream)") if len(hdr) < 20: raise Scapy_Exception("Invalid pcap file (too short)") vermaj, vermin, tz, sig, snaplen, linktype = struct.unpack( @@ -1697,7 +1701,8 @@ def __init__(self, filename, fdesc=None, magic=None): # type: ignore try: self._read_block_shb() - except EOFError: + except (EOFError, OSError, OverflowError, zlib.error) as e: + warning(f"PcapNg: {e}") raise Scapy_Exception( "The first SHB of the pcapng file is malformed !" ) @@ -1801,7 +1806,11 @@ def _read_packet(self, size=MTU): # type: ignore """ while True: - res = self._read_block(size=size) + try: + res = self._read_block(size=size) + except (OSError, OverflowError, zlib.error) as e: + warning(f"PcapNg: {e}") + raise EOFError if res is not None: return res diff --git a/test/regression.uts b/test/regression.uts index 4e3fced7e75..1807df69758 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -2548,6 +2548,30 @@ with mock.patch("scapy.utils.warning") as warning: for call in warning.call_args_list ) == 3 +# Issue 568035799 +import zlib + +from scapy.error import Scapy_Exception + +class CorruptedStream(BytesIO): + def read(self, *args, **kwargs): + if self.tell() >= self.getbuffer().nbytes: + raise zlib.error( + "Error -3 while decompressing data: " + "invalid distance too far back" + ) + return BytesIO.read(self, *args, **kwargs) + +with mock.patch("scapy.utils.warning") as warning: + tmpfile = get_temp_file(autoext=".pcapng") + writer = RawPcapNgWriter(tmpfile) + writer._write_block_shb() + writer.f.close() + with open(tmpfile, "rb") as fd: + capture = fd.read() + rdpcap(CorruptedStream(capture)) + any("PcapNg" in call.args[0] for call in warning.call_args_list) + # Issue #69628 file = BytesIO(b"\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x01\x00\x00\x00\x04{\xdcf\xc2\xa5\x07\x008\x00\x00\x008\x00\x00\x00A]+\xdb]\x04\x8e(6\n\x99\xcb\x08\x00E\x00\x00*\x00\x01\x00\x00@\x06\xe3V\x07\x87\xa5m\x17\x15\xd3m\x01\x85\x01\x85\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\xc5_\x00\x000\x00") l = rdpcap(file)