From f20b740cd27e0abe531f01763b2cfab7e59a5abf Mon Sep 17 00:00:00 2001 From: Clinton Thomas <1033162+KernelClint@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:25:47 -0400 Subject: [PATCH 1/2] tftp: extend multi-block read results in place AI-Assisted: yes (GPT-5.6-Cyber) --- scapy/layers/tftp.py | 10 +++++++++- test/scapy/layers/tftp.uts | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/scapy/layers/tftp.py b/scapy/layers/tftp.py index fcd925c3f57..4560f931405 100644 --- a/scapy/layers/tftp.py +++ b/scapy/layers/tftp.py @@ -227,10 +227,18 @@ def RECEIVING(self, pkt): recvd = pkt[conf.raw_layer].load else: recvd = b"" - self.res += recvd + if not self.res: + self.res = recvd + elif isinstance(self.res, bytes): + self.res = bytearray(self.res) + self.res.extend(recvd) + else: + self.res.extend(recvd) self.awaiting += 1 if len(recvd) == self.blocksize: raise self.WAITING() + if isinstance(self.res, bytearray): + self.res = bytes(self.res) raise self.END() # ERROR diff --git a/test/scapy/layers/tftp.uts b/test/scapy/layers/tftp.uts index c54e271a08e..595840782c6 100644 --- a/test/scapy/layers/tftp.uts +++ b/test/scapy/layers/tftp.uts @@ -70,6 +70,28 @@ tftp_read = TFTP_read("file.txt", "1.2.3.4", sport=0x2807, res = tftp_read.run() assert res == (b"P" * 512 + b"<3") += TFTP_read extends one response buffer after the first block +from scapy.automaton import ATMT +from scapy.layers.tftp import TFTP_read +from scapy.packet import Raw + +client = object.__new__(TFTP_read) +client.res = b"" +client.awaiting = 1 +client.blocksize = 512 + +def receive_full_block(): + try: + TFTP_read.RECEIVING.atmt_origfunc(client, Raw(b"A" * 512)) + except ATMT.NewStateRequested: + pass + +receive_full_block() +receive_full_block() +response_buffer = client.res +receive_full_block() +assert client.res is response_buffer + = TFTP_read() automaton error ~ linux From 5c2606f60d56bc2bdc74fd284a9777ccb133eff8 Mon Sep 17 00:00:00 2001 From: Clinton Thomas <1033162+KernelClint@users.noreply.github.com> Date: Thu, 27 Aug 2026 10:12:10 -0400 Subject: [PATCH 2/2] tftp: keep the read buffer as a bytearray throughout Addresses review feedback on #5110: rather than switching self.res between bytes and bytearray, initialise it as a bytearray and convert once when the automaton returns. Removes the isinstance branching; the accumulate line goes back to a plain +=. AI-Assisted: yes (GPT-5.6-Sol) --- scapy/layers/tftp.py | 14 +++----------- test/scapy/layers/tftp.uts | 2 +- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/scapy/layers/tftp.py b/scapy/layers/tftp.py index 4560f931405..023d1193726 100644 --- a/scapy/layers/tftp.py +++ b/scapy/layers/tftp.py @@ -179,7 +179,7 @@ def BEGIN(self): self.my_tid = self.sport or RandShort()._fix() bind_bottom_up(UDP, TFTP, dport=self.my_tid) self.server_tid = None - self.res = b"" + self.res = bytearray() self.l3 = IP(dst=self.server) / UDP(sport=self.my_tid, dport=self.port) / TFTP() # noqa: E501 self.last_packet = self.l3 / TFTP_RRQ(filename=self.filename, mode="octet") # noqa: E501 @@ -227,18 +227,10 @@ def RECEIVING(self, pkt): recvd = pkt[conf.raw_layer].load else: recvd = b"" - if not self.res: - self.res = recvd - elif isinstance(self.res, bytes): - self.res = bytearray(self.res) - self.res.extend(recvd) - else: - self.res.extend(recvd) + self.res += recvd self.awaiting += 1 if len(recvd) == self.blocksize: raise self.WAITING() - if isinstance(self.res, bytearray): - self.res = bytes(self.res) raise self.END() # ERROR @@ -251,7 +243,7 @@ def ERROR(self, pkt): @ATMT.state(final=1) def END(self): split_bottom_up(UDP, TFTP, dport=self.my_tid) - return self.res + return bytes(self.res) class TFTP_write(Automaton): diff --git a/test/scapy/layers/tftp.uts b/test/scapy/layers/tftp.uts index 595840782c6..756a735d639 100644 --- a/test/scapy/layers/tftp.uts +++ b/test/scapy/layers/tftp.uts @@ -76,7 +76,7 @@ from scapy.layers.tftp import TFTP_read from scapy.packet import Raw client = object.__new__(TFTP_read) -client.res = b"" +client.res = bytearray() client.awaiting = 1 client.blocksize = 512