We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Address PEP 706 - Filter for tarfile.extractall
Given proposal improves security of tarfile extraction to help avoid CVE-2007-4559.

- In Python 3.12-3.13, a DeprecationWarning is emitted and extraction uses `fully_trusted` filter.
- In Python 3.14+, it will use the `data` filter.

It seems given proposal was backported also to older version of Python.

Reference: https://peps.python.org/pep-0706/


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `master/buildbot/process/remotetransfer.py`
Content:
```
1 # This file is part of Buildbot.  Buildbot is free software: you can
2 # redistribute it and/or modify it under the terms of the GNU General Public
3 # License as published by the Free Software Foundation, version 2.
4 #
5 # This program is distributed in the hope that it will be useful, but WITHOUT
6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
8 # details.
9 #
10 # You should have received a copy of the GNU General Public License along with
11 # this program; if not, write to the Free Software Foundation, Inc., 51
12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13 #
14 # Copyright Buildbot Team Members
15 
16 """
17 module for regrouping all FileWriterImpl and FileReaderImpl away from steps
18 """
19 
20 import os
21 import tarfile
22 import tempfile
23 from io import BytesIO
24 
25 from buildbot.util import bytes2unicode
26 from buildbot.util import unicode2bytes
27 from buildbot.worker.protocols import base
28 
29 
30 class FileWriter(base.FileWriterImpl):
31 
32     """
33     Helper class that acts as a file-object with write access
34     """
35 
36     def __init__(self, destfile, maxsize, mode):
37         # Create missing directories.
38         destfile = os.path.abspath(destfile)
39         dirname = os.path.dirname(destfile)
40         if not os.path.exists(dirname):
41             os.makedirs(dirname)
42 
43         self.destfile = destfile
44         self.mode = mode
45         fd, self.tmpname = tempfile.mkstemp(dir=dirname, prefix='buildbot-transfer-')
46         self.fp = os.fdopen(fd, 'wb')
47         self.remaining = maxsize
48 
49     def remote_write(self, data):
50         """
51         Called from remote worker to write L{data} to L{fp} within boundaries
52         of L{maxsize}
53 
54         @type  data: C{string}
55         @param data: String of data to write
56         """
57         data = unicode2bytes(data)
58         if self.remaining is not None:
59             if len(data) > self.remaining:
60                 data = data[:self.remaining]
61             self.fp.write(data)
62             self.remaining = self.remaining - len(data)
63         else:
64             self.fp.write(data)
65 
66     def remote_utime(self, accessed_modified):
67         os.utime(self.destfile, accessed_modified)
68 
69     def remote_close(self):
70         """
71         Called by remote worker to state that no more data will be transferred
72         """
73         self.fp.close()
74         self.fp = None
75         # on windows, os.rename does not automatically unlink, so do it
76         # manually
77         if os.path.exists(self.destfile):
78             os.unlink(self.destfile)
79         os.rename(self.tmpname, self.destfile)
80         self.tmpname = None
81         if self.mode is not None:
82             os.chmod(self.destfile, self.mode)
83 
84     def cancel(self):
85         # unclean shutdown, the file is probably truncated, so delete it
86         # altogether rather than deliver a corrupted file
87         fp = getattr(self, "fp", None)
88         if fp:
89             fp.close()
90             if self.destfile and os.path.exists(self.destfile):
91                 os.unlink(self.destfile)
92             if self.tmpname and os.path.exists(self.tmpname):
93                 os.unlink(self.tmpname)
94 
95 
96 class DirectoryWriter(FileWriter):
97 
98     """
99     A DirectoryWriter is implemented as a FileWriter, with an added post-processing
100     step to unpack the archive, once the transfer has completed.
101     """
102 
103     def __init__(self, destroot, maxsize, compress, mode):
104         self.destroot = destroot
105         self.compress = compress
106 
107         self.fd, self.tarname = tempfile.mkstemp(prefix='buildbot-transfer-')
108         os.close(self.fd)
109 
110         super().__init__(self.tarname, maxsize, mode)
111 
112     def remote_unpack(self):
113         """
114         Called by remote worker to state that no more data will be transferred
115         """
116         # Make sure remote_close is called, otherwise atomic rename won't happen
117         self.remote_close()
118 
119         # Map configured compression to a TarFile setting
120         if self.compress == 'bz2':
121             mode = 'r|bz2'
122         elif self.compress == 'gz':
123             mode = 'r|gz'
124         else:
125             mode = 'r'
126 
127         # Unpack archive and clean up after self
128         with tarfile.open(name=self.tarname, mode=mode) as archive:
129             archive.extractall(path=self.destroot)
130         os.remove(self.tarname)
131 
132 
133 class FileReader(base.FileReaderImpl):
134 
135     """
136     Helper class that acts as a file-object with read access
137     """
138 
139     def __init__(self, fp):
140         self.fp = fp
141 
142     def remote_read(self, maxlength):
143         """
144         Called from remote worker to read at most L{maxlength} bytes of data
145 
146         @type  maxlength: C{integer}
147         @param maxlength: Maximum number of data bytes that can be returned
148 
149         @return: Data read from L{fp}
150         @rtype: C{string} of bytes read from file
151         """
152         if self.fp is None:
153             return ''
154 
155         data = self.fp.read(maxlength)
156         return data
157 
158     def remote_close(self):
159         """
160         Called by remote worker to state that no more data will be transferred
161         """
162         if self.fp is not None:
163             self.fp.close()
164             self.fp = None
165 
166 
167 class StringFileWriter(base.FileWriterImpl):
168 
169     """
170     FileWriter class that just puts received data into a buffer.
171 
172     Used to upload a file from worker for inline processing rather than
173     writing into a file on master.
174     """
175 
176     def __init__(self):
177         self.buffer = ""
178 
179     def remote_write(self, data):
180         self.buffer += bytes2unicode(data)
181 
182     def remote_close(self):
183         pass
184 
185 
186 class StringFileReader(FileReader):
187 
188     """
189     FileWriter class that just buid send data from a string.
190 
191     Used to download a file to worker from local string rather than first
192     writing into a file on master.
193     """
194 
195     def __init__(self, s):
196         s = unicode2bytes(s)
197         super().__init__(BytesIO(s))
198
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/master/buildbot/process/remotetransfer.py b/master/buildbot/process/remotetransfer.py
--- a/master/buildbot/process/remotetransfer.py
+++ b/master/buildbot/process/remotetransfer.py
@@ -126,7 +126,10 @@
 
         # Unpack archive and clean up after self
         with tarfile.open(name=self.tarname, mode=mode) as archive:
-            archive.extractall(path=self.destroot)
+            if hasattr(tarfile, 'data_filter'):
+                archive.extractall(path=self.destroot, filter='data')
+            else:
+                archive.extractall(path=self.destroot)
         os.remove(self.tarname)

{"golden_diff": "diff --git a/master/buildbot/process/remotetransfer.py b/master/buildbot/process/remotetransfer.py\n--- a/master/buildbot/process/remotetransfer.py\n+++ b/master/buildbot/process/remotetransfer.py\n@@ -126,7 +126,10 @@\n \n         # Unpack archive and clean up after self\n         with tarfile.open(name=self.tarname, mode=mode) as archive:\n-            archive.extractall(path=self.destroot)\n+            if hasattr(tarfile, 'data_filter'):\n+                archive.extractall(path=self.destroot, filter='data')\n+            else:\n+                archive.extractall(path=self.destroot)\n         os.remove(self.tarname)\n", "issue": "Address PEP 706 - Filter for tarfile.extractall\nGiven proposal improves security of tarfile extraction to help avoid CVE-2007-4559.\r\n\r\n- In Python 3.12-3.13, a DeprecationWarning is emitted and extraction uses `fully_trusted` filter.\r\n- In Python 3.14+, it will use the `data` filter.\r\n\r\nIt seems given proposal was backported also to older version of Python.\r\n\r\nReference: https://peps.python.org/pep-0706/\r\n\n", "before_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\n\"\"\"\nmodule for regrouping all FileWriterImpl and FileReaderImpl away from steps\n\"\"\"\n\nimport os\nimport tarfile\nimport tempfile\nfrom io import BytesIO\n\nfrom buildbot.util import bytes2unicode\nfrom buildbot.util import unicode2bytes\nfrom buildbot.worker.protocols import base\n\n\nclass FileWriter(base.FileWriterImpl):\n\n    \"\"\"\n    Helper class that acts as a file-object with write access\n    \"\"\"\n\n    def __init__(self, destfile, maxsize, mode):\n        # Create missing directories.\n        destfile = os.path.abspath(destfile)\n        dirname = os.path.dirname(destfile)\n        if not os.path.exists(dirname):\n            os.makedirs(dirname)\n\n        self.destfile = destfile\n        self.mode = mode\n        fd, self.tmpname = tempfile.mkstemp(dir=dirname, prefix='buildbot-transfer-')\n        self.fp = os.fdopen(fd, 'wb')\n        self.remaining = maxsize\n\n    def remote_write(self, data):\n        \"\"\"\n        Called from remote worker to write L{data} to L{fp} within boundaries\n        of L{maxsize}\n\n        @type  data: C{string}\n        @param data: String of data to write\n        \"\"\"\n        data = unicode2bytes(data)\n        if self.remaining is not None:\n            if len(data) > self.remaining:\n                data = data[:self.remaining]\n            self.fp.write(data)\n            self.remaining = self.remaining - len(data)\n        else:\n            self.fp.write(data)\n\n    def remote_utime(self, accessed_modified):\n        os.utime(self.destfile, accessed_modified)\n\n    def remote_close(self):\n        \"\"\"\n        Called by remote worker to state that no more data will be transferred\n        \"\"\"\n        self.fp.close()\n        self.fp = None\n        # on windows, os.rename does not automatically unlink, so do it\n        # manually\n        if os.path.exists(self.destfile):\n            os.unlink(self.destfile)\n        os.rename(self.tmpname, self.destfile)\n        self.tmpname = None\n        if self.mode is not None:\n            os.chmod(self.destfile, self.mode)\n\n    def cancel(self):\n        # unclean shutdown, the file is probably truncated, so delete it\n        # altogether rather than deliver a corrupted file\n        fp = getattr(self, \"fp\", None)\n        if fp:\n            fp.close()\n            if self.destfile and os.path.exists(self.destfile):\n                os.unlink(self.destfile)\n            if self.tmpname and os.path.exists(self.tmpname):\n                os.unlink(self.tmpname)\n\n\nclass DirectoryWriter(FileWriter):\n\n    \"\"\"\n    A DirectoryWriter is implemented as a FileWriter, with an added post-processing\n    step to unpack the archive, once the transfer has completed.\n    \"\"\"\n\n    def __init__(self, destroot, maxsize, compress, mode):\n        self.destroot = destroot\n        self.compress = compress\n\n        self.fd, self.tarname = tempfile.mkstemp(prefix='buildbot-transfer-')\n        os.close(self.fd)\n\n        super().__init__(self.tarname, maxsize, mode)\n\n    def remote_unpack(self):\n        \"\"\"\n        Called by remote worker to state that no more data will be transferred\n        \"\"\"\n        # Make sure remote_close is called, otherwise atomic rename won't happen\n        self.remote_close()\n\n        # Map configured compression to a TarFile setting\n        if self.compress == 'bz2':\n            mode = 'r|bz2'\n        elif self.compress == 'gz':\n            mode = 'r|gz'\n        else:\n            mode = 'r'\n\n        # Unpack archive and clean up after self\n        with tarfile.open(name=self.tarname, mode=mode) as archive:\n            archive.extractall(path=self.destroot)\n        os.remove(self.tarname)\n\n\nclass FileReader(base.FileReaderImpl):\n\n    \"\"\"\n    Helper class that acts as a file-object with read access\n    \"\"\"\n\n    def __init__(self, fp):\n        self.fp = fp\n\n    def remote_read(self, maxlength):\n        \"\"\"\n        Called from remote worker to read at most L{maxlength} bytes of data\n\n        @type  maxlength: C{integer}\n        @param maxlength: Maximum number of data bytes that can be returned\n\n        @return: Data read from L{fp}\n        @rtype: C{string} of bytes read from file\n        \"\"\"\n        if self.fp is None:\n            return ''\n\n        data = self.fp.read(maxlength)\n        return data\n\n    def remote_close(self):\n        \"\"\"\n        Called by remote worker to state that no more data will be transferred\n        \"\"\"\n        if self.fp is not None:\n            self.fp.close()\n            self.fp = None\n\n\nclass StringFileWriter(base.FileWriterImpl):\n\n    \"\"\"\n    FileWriter class that just puts received data into a buffer.\n\n    Used to upload a file from worker for inline processing rather than\n    writing into a file on master.\n    \"\"\"\n\n    def __init__(self):\n        self.buffer = \"\"\n\n    def remote_write(self, data):\n        self.buffer += bytes2unicode(data)\n\n    def remote_close(self):\n        pass\n\n\nclass StringFileReader(FileReader):\n\n    \"\"\"\n    FileWriter class that just buid send data from a string.\n\n    Used to download a file to worker from local string rather than first\n    writing into a file on master.\n    \"\"\"\n\n    def __init__(self, s):\n        s = unicode2bytes(s)\n        super().__init__(BytesIO(s))\n", "path": "master/buildbot/process/remotetransfer.py"}], "after_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\n\"\"\"\nmodule for regrouping all FileWriterImpl and FileReaderImpl away from steps\n\"\"\"\n\nimport os\nimport tarfile\nimport tempfile\nfrom io import BytesIO\n\nfrom buildbot.util import bytes2unicode\nfrom buildbot.util import unicode2bytes\nfrom buildbot.worker.protocols import base\n\n\nclass FileWriter(base.FileWriterImpl):\n\n    \"\"\"\n    Helper class that acts as a file-object with write access\n    \"\"\"\n\n    def __init__(self, destfile, maxsize, mode):\n        # Create missing directories.\n        destfile = os.path.abspath(destfile)\n        dirname = os.path.dirname(destfile)\n        if not os.path.exists(dirname):\n            os.makedirs(dirname)\n\n        self.destfile = destfile\n        self.mode = mode\n        fd, self.tmpname = tempfile.mkstemp(dir=dirname, prefix='buildbot-transfer-')\n        self.fp = os.fdopen(fd, 'wb')\n        self.remaining = maxsize\n\n    def remote_write(self, data):\n        \"\"\"\n        Called from remote worker to write L{data} to L{fp} within boundaries\n        of L{maxsize}\n\n        @type  data: C{string}\n        @param data: String of data to write\n        \"\"\"\n        data = unicode2bytes(data)\n        if self.remaining is not None:\n            if len(data) > self.remaining:\n                data = data[:self.remaining]\n            self.fp.write(data)\n            self.remaining = self.remaining - len(data)\n        else:\n            self.fp.write(data)\n\n    def remote_utime(self, accessed_modified):\n        os.utime(self.destfile, accessed_modified)\n\n    def remote_close(self):\n        \"\"\"\n        Called by remote worker to state that no more data will be transferred\n        \"\"\"\n        self.fp.close()\n        self.fp = None\n        # on windows, os.rename does not automatically unlink, so do it\n        # manually\n        if os.path.exists(self.destfile):\n            os.unlink(self.destfile)\n        os.rename(self.tmpname, self.destfile)\n        self.tmpname = None\n        if self.mode is not None:\n            os.chmod(self.destfile, self.mode)\n\n    def cancel(self):\n        # unclean shutdown, the file is probably truncated, so delete it\n        # altogether rather than deliver a corrupted file\n        fp = getattr(self, \"fp\", None)\n        if fp:\n            fp.close()\n            if self.destfile and os.path.exists(self.destfile):\n                os.unlink(self.destfile)\n            if self.tmpname and os.path.exists(self.tmpname):\n                os.unlink(self.tmpname)\n\n\nclass DirectoryWriter(FileWriter):\n\n    \"\"\"\n    A DirectoryWriter is implemented as a FileWriter, with an added post-processing\n    step to unpack the archive, once the transfer has completed.\n    \"\"\"\n\n    def __init__(self, destroot, maxsize, compress, mode):\n        self.destroot = destroot\n        self.compress = compress\n\n        self.fd, self.tarname = tempfile.mkstemp(prefix='buildbot-transfer-')\n        os.close(self.fd)\n\n        super().__init__(self.tarname, maxsize, mode)\n\n    def remote_unpack(self):\n        \"\"\"\n        Called by remote worker to state that no more data will be transferred\n        \"\"\"\n        # Make sure remote_close is called, otherwise atomic rename won't happen\n        self.remote_close()\n\n        # Map configured compression to a TarFile setting\n        if self.compress == 'bz2':\n            mode = 'r|bz2'\n        elif self.compress == 'gz':\n            mode = 'r|gz'\n        else:\n            mode = 'r'\n\n        # Unpack archive and clean up after self\n        with tarfile.open(name=self.tarname, mode=mode) as archive:\n            if hasattr(tarfile, 'data_filter'):\n                archive.extractall(path=self.destroot, filter='data')\n            else:\n                archive.extractall(path=self.destroot)\n        os.remove(self.tarname)\n\n\nclass FileReader(base.FileReaderImpl):\n\n    \"\"\"\n    Helper class that acts as a file-object with read access\n    \"\"\"\n\n    def __init__(self, fp):\n        self.fp = fp\n\n    def remote_read(self, maxlength):\n        \"\"\"\n        Called from remote worker to read at most L{maxlength} bytes of data\n\n        @type  maxlength: C{integer}\n        @param maxlength: Maximum number of data bytes that can be returned\n\n        @return: Data read from L{fp}\n        @rtype: C{string} of bytes read from file\n        \"\"\"\n        if self.fp is None:\n            return ''\n\n        data = self.fp.read(maxlength)\n        return data\n\n    def remote_close(self):\n        \"\"\"\n        Called by remote worker to state that no more data will be transferred\n        \"\"\"\n        if self.fp is not None:\n            self.fp.close()\n            self.fp = None\n\n\nclass StringFileWriter(base.FileWriterImpl):\n\n    \"\"\"\n    FileWriter class that just puts received data into a buffer.\n\n    Used to upload a file from worker for inline processing rather than\n    writing into a file on master.\n    \"\"\"\n\n    def __init__(self):\n        self.buffer = \"\"\n\n    def remote_write(self, data):\n        self.buffer += bytes2unicode(data)\n\n    def remote_close(self):\n        pass\n\n\nclass StringFileReader(FileReader):\n\n    \"\"\"\n    FileWriter class that just buid send data from a string.\n\n    Used to download a file to worker from local string rather than first\n    writing into a file on master.\n    \"\"\"\n\n    def __init__(self, s):\n        s = unicode2bytes(s)\n        super().__init__(BytesIO(s))\n", "path": "master/buildbot/process/remotetransfer.py"}]}