diff -pruN 2.7.18-13/debian/changelog 2.7.18-13.2/debian/changelog
--- 2.7.18-13/debian/changelog	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/changelog	2022-08-01 09:11:46.000000000 +0000
@@ -1,3 +1,20 @@
+python2.7 (2.7.18-13.2) unstable; urgency=medium
+
+  * Non-maintainer upload.
+
+  [ Matthias Klose ]
+  * Hard-code dependency on libssl3 instead of libssl1.1. (Closes: #1011118)
+
+ -- Unit 193 <unit193@debian.org>  Mon, 01 Aug 2022 02:23:55 -0400
+
+python2.7 (2.7.18-13.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * CVE-2021-4189: make ftplib not trust the PASV response.
+  * CVE-2021-23336: only use '&' as a query string separator.
+
+ -- Anton Gladky <gladk@debian.org>  Mon, 28 Mar 2022 22:47:09 +0200
+
 python2.7 (2.7.18-13) unstable; urgency=medium
 
   * Skip tests requiring TLS 1.2 under OpenSSL 3.
diff -pruN 2.7.18-13/debian/control 2.7.18-13.2/debian/control
--- 2.7.18-13/debian/control	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/control	2022-08-01 09:11:46.000000000 +0000
@@ -44,7 +44,7 @@ Package: libpython2.7-stdlib
 Architecture: any
 Multi-Arch: same
 Priority: optional
-Depends: libpython2.7-minimal (= ${binary:Version}), libssl1.1 (>= 1.1.1), media-types | mime-support, ${shlibs:Depends}, ${misc:Depends}
+Depends: libpython2.7-minimal (= ${binary:Version}), libssl3, media-types | mime-support, ${shlibs:Depends}, ${misc:Depends}
 Provides: python2.7-cjkcodecs, python2.7-ctypes, python2.7-elementtree, python2.7-celementtree, python2.7-wsgiref, python2.7-profiler, python2.7-argparse, python-argparse
 Replaces: python2.7 (<< 2.7.5-0~), libpython2.7-testsuite (<< 2.7.13-4)
 Breaks: python-urllib3 (<< 1.9.1-3), ${pyfpe:Breaks}, ${python27:Breaks}
diff -pruN 2.7.18-13/debian/control.in 2.7.18-13.2/debian/control.in
--- 2.7.18-13/debian/control.in	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/control.in	2022-08-01 09:11:46.000000000 +0000
@@ -44,7 +44,7 @@ Package: lib@PVER@-stdlib
 Architecture: any
 Multi-Arch: same
 Priority: @PRIO@
-Depends: lib@PVER@-minimal (= ${binary:Version}), libssl1.1 (>= 1.1.1), media-types | mime-support, ${shlibs:Depends}, ${misc:Depends}
+Depends: lib@PVER@-minimal (= ${binary:Version}), libssl3, media-types | mime-support, ${shlibs:Depends}, ${misc:Depends}
 Provides: @PVER@-cjkcodecs, @PVER@-ctypes, @PVER@-elementtree, @PVER@-celementtree, @PVER@-wsgiref, @PVER@-profiler, @PVER@-argparse, python-argparse
 Replaces: @PVER@ (<< 2.7.5-0~), lib@PVER@-testsuite (<< 2.7.13-4)
 Breaks: python-urllib3 (<< 1.9.1-3), ${pyfpe:Breaks}, ${python27:Breaks}
diff -pruN 2.7.18-13/debian/.gitlab-ci.yml 2.7.18-13.2/debian/.gitlab-ci.yml
--- 2.7.18-13/debian/.gitlab-ci.yml	1970-01-01 00:00:00.000000000 +0000
+++ 2.7.18-13.2/debian/.gitlab-ci.yml	2022-08-01 09:11:46.000000000 +0000
@@ -0,0 +1,8 @@
+include:
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
+
+variables:
+  RELEASE: 'unstable'
+  SALSA_CI_COMPONENTS: 'main contrib non-free'
+  SALSA_CI_DISABLE_REPROTEST: 1
+  DEB_BUILD_OPTIONS: nocheck
diff -pruN 2.7.18-13/debian/patches/add-python-config-sh.diff 2.7.18-13.2/debian/patches/add-python-config-sh.diff
--- 2.7.18-13/debian/patches/add-python-config-sh.diff	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/patches/add-python-config-sh.diff	2022-08-01 09:11:46.000000000 +0000
@@ -1,5 +1,7 @@
---- a/Makefile.pre.in
-+++ b/Makefile.pre.in
+Index: python2.7/Makefile.pre.in
+===================================================================
+--- python2.7.orig/Makefile.pre.in
++++ python2.7/Makefile.pre.in
 @@ -1196,6 +1196,8 @@ python-config: $(srcdir)/Misc/python-con
  	# Substitution happens here, as the completely-expanded BINDIR
  	# is not available in configure
@@ -17,8 +19,10 @@
  	@if [ -s Modules/python.exp -a \
  		"`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \
  		echo; echo "Installing support files for building shared extension modules on AIX:"; \
---- a/Misc/python-config.in
-+++ b/Misc/python-config.in
+Index: python2.7/Misc/python-config.in
+===================================================================
+--- python2.7.orig/Misc/python-config.in
++++ python2.7/Misc/python-config.in
 @@ -56,3 +56,11 @@ for opt in opt_flags:
                  libs.extend(getvar('LINKFORSHARED').split())
          print ' '.join(libs)
@@ -31,8 +35,10 @@
 +
 +    elif opt == '--configdir':
 +        print sysconfig.get_config_var('LIBPL')
+Index: python2.7/Misc/python-config.sh.in
+===================================================================
 --- /dev/null
-+++ b/Misc/python-config.sh.in
++++ python2.7/Misc/python-config.sh.in
 @@ -0,0 +1,103 @@
 +#!/bin/sh
 +
@@ -137,8 +143,10 @@
 +        ;;
 +esac
 +done
---- a/configure.ac
-+++ b/configure.ac
+Index: python2.7/configure.ac
+===================================================================
+--- python2.7.orig/configure.ac
++++ python2.7/configure.ac
 @@ -915,6 +915,7 @@ fi
  
  # Other platforms follow
@@ -163,7 +171,7 @@
  
  if test "$cross_compiling" = yes; then
  	RUNSHARED=
-@@ -4959,7 +4962,7 @@ AC_MSG_RESULT($ENSUREPIP)
+@@ -4962,7 +4965,7 @@ AC_MSG_RESULT($ENSUREPIP)
  AC_SUBST(ENSUREPIP)
  
  # generate output files
diff -pruN 2.7.18-13/debian/patches/CVE-2021-23336.patch 2.7.18-13.2/debian/patches/CVE-2021-23336.patch
--- 2.7.18-13/debian/patches/CVE-2021-23336.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.7.18-13.2/debian/patches/CVE-2021-23336.patch	2022-08-01 09:11:46.000000000 +0000
@@ -0,0 +1,373 @@
+diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst
+index ecd62c8..f2016a2 100644
+--- a/Doc/library/cgi.rst
++++ b/Doc/library/cgi.rst
+@@ -285,10 +285,10 @@ These are useful if you want more control, or if you want to employ some of the
+ algorithms implemented in this module in other circumstances.
+ 
+ 
+-.. function:: parse(fp[, environ[, keep_blank_values[, strict_parsing]]])
++.. function:: parse(fp[, environ[, keep_blank_values[, strict_parsing[, separator="&"]]]])
+ 
+    Parse a query in the environment or from a file (the file defaults to
+-   ``sys.stdin`` and environment defaults to ``os.environ``).  The *keep_blank_values* and *strict_parsing* parameters are
++   ``sys.stdin`` and environment defaults to ``os.environ``).  The *keep_blank_values*, *strict_parsing*  and *separator* parameters are
+    passed to :func:`urlparse.parse_qs` unchanged.
+ 
+ 
+@@ -302,7 +302,7 @@ algorithms implemented in this module in other circumstances.
+    This function is deprecated in this module. Use :func:`urlparse.parse_qsl`
+    instead. It is maintained here only for backward compatibility.
+ 
+-.. function:: parse_multipart(fp, pdict)
++.. function:: parse_multipart(fp, pdict, separator="&")
+ 
+    Parse input of type :mimetype:`multipart/form-data` (for  file uploads).
+    Arguments are *fp* for the input file and *pdict* for a dictionary containing
+diff --git a/Doc/library/urlparse.rst b/Doc/library/urlparse.rst
+index 0989c88..ca05e1b 100644
+--- a/Doc/library/urlparse.rst
++++ b/Doc/library/urlparse.rst
+@@ -136,7 +136,7 @@ The :mod:`urlparse` module defines the following functions:
+       now raise :exc:`ValueError`.
+ 
+ 
+-.. function:: parse_qs(qs[, keep_blank_values[, strict_parsing[, max_num_fields]]])
++.. function:: parse_qs(qs[, keep_blank_values[, strict_parsing[, max_num_fields[, separator='&']]]])
+ 
+    Parse a query string given as a string argument (data of type
+    :mimetype:`application/x-www-form-urlencoded`).  Data are returned as a
+@@ -153,6 +153,8 @@ The :mod:`urlparse` module defines the following functions:
+    parsing errors.  If false (the default), errors are silently ignored.  If true,
+    errors raise a :exc:`ValueError` exception.
+ 
++   The optional argument *separator* is the symbol to use for separating the query arguments. It defaults to `&`.
++
+    The optional argument *max_num_fields* is the maximum number of fields to
+    read. If set, then throws a :exc:`ValueError` if there are more than
+    *max_num_fields* fields read.
+@@ -166,7 +168,7 @@ The :mod:`urlparse` module defines the following functions:
+    .. versionchanged:: 2.7.16
+       Added *max_num_fields* parameter.
+ 
+-.. function:: parse_qsl(qs[, keep_blank_values[, strict_parsing[, max_num_fields]]])
++.. function:: parse_qsl(qs[, keep_blank_values[, strict_parsing[, max_num_fields[, separator='&']]]])
+ 
+    Parse a query string given as a string argument (data of type
+    :mimetype:`application/x-www-form-urlencoded`).  Data are returned as a list of
+@@ -182,6 +184,8 @@ The :mod:`urlparse` module defines the following functions:
+    parsing errors.  If false (the default), errors are silently ignored.  If true,
+    errors raise a :exc:`ValueError` exception.
+ 
++   The optional argument *separator* is the symbol to use for separating the query arguments. It defaults to `&`.
++
+    The optional argument *max_num_fields* is the maximum number of fields to
+    read. If set, then throws a :exc:`ValueError` if there are more than
+    *max_num_fields* fields read.
+diff --git a/Lib/cgi.py b/Lib/cgi.py
+index 5b903e0..715433b 100755
+--- a/Lib/cgi.py
++++ b/Lib/cgi.py
+@@ -121,7 +121,7 @@ log = initlog           # The current logging function
+ # 0 ==> unlimited input
+ maxlen = 0
+ 
+-def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
++def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0, separator='&'):
+     """Parse a query in the environment or from a file (default stdin)
+ 
+         Arguments, all optional:
+@@ -140,6 +140,8 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
+         strict_parsing: flag indicating what to do with parsing errors.
+             If false (the default), errors are silently ignored.
+             If true, errors raise a ValueError exception.
++        separator: str. The symbol to use for separating the query arguments.
++            Defaults to &.
+     """
+     if fp is None:
+         fp = sys.stdin
+@@ -148,7 +150,7 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
+     if environ['REQUEST_METHOD'] == 'POST':
+         ctype, pdict = parse_header(environ['CONTENT_TYPE'])
+         if ctype == 'multipart/form-data':
+-            return parse_multipart(fp, pdict)
++            return parse_multipart(fp, pdict, separator=separator)
+         elif ctype == 'application/x-www-form-urlencoded':
+             clength = int(environ['CONTENT_LENGTH'])
+             if maxlen and clength > maxlen:
+@@ -171,27 +173,27 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
+         else:
+             qs = ""
+         environ['QUERY_STRING'] = qs    # XXX Shouldn't, really
+-    return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
++    return urlparse.parse_qs(qs, keep_blank_values, strict_parsing, separator=separator)
+ 
+ 
+ # parse query string function called from urlparse,
+ # this is done in order to maintain backward compatibility.
+ 
+-def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
++def parse_qs(qs, keep_blank_values=0, strict_parsing=0, separator='&'):
+     """Parse a query given as a string argument."""
+     warn("cgi.parse_qs is deprecated, use urlparse.parse_qs instead",
+          PendingDeprecationWarning, 2)
+-    return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
++    return urlparse.parse_qs(qs, keep_blank_values, strict_parsing, separator=separator)
+ 
+ 
+-def parse_qsl(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None):
++def parse_qsl(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None, separator='&'):
+     """Parse a query given as a string argument."""
+     warn("cgi.parse_qsl is deprecated, use urlparse.parse_qsl instead",
+          PendingDeprecationWarning, 2)
+     return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing,
+-                              max_num_fields)
++                              max_num_fields, separator=separator)
+ 
+-def parse_multipart(fp, pdict):
++def parse_multipart(fp, pdict, separator='&'):
+     """Parse multipart input.
+ 
+     Arguments:
+@@ -395,7 +397,7 @@ class FieldStorage:
+ 
+     def __init__(self, fp=None, headers=None, outerboundary="",
+                  environ=os.environ, keep_blank_values=0, strict_parsing=0,
+-                 max_num_fields=None):
++                 max_num_fields=None, separator='&'):
+         """Constructor.  Read multipart/* until last part.
+ 
+         Arguments, all optional:
+@@ -430,6 +432,7 @@ class FieldStorage:
+         self.keep_blank_values = keep_blank_values
+         self.strict_parsing = strict_parsing
+         self.max_num_fields = max_num_fields
++        self.separator = separator
+         if 'REQUEST_METHOD' in environ:
+             method = environ['REQUEST_METHOD'].upper()
+         self.qs_on_post = None
+@@ -613,7 +616,7 @@ class FieldStorage:
+         if self.qs_on_post:
+             qs += '&' + self.qs_on_post
+         query = urlparse.parse_qsl(qs, self.keep_blank_values,
+-                                   self.strict_parsing, self.max_num_fields)
++                                   self.strict_parsing, self.max_num_fields, separator=self.separator)
+         self.list = [MiniFieldStorage(key, value) for key, value in query]
+         self.skip_lines()
+ 
+@@ -629,7 +632,7 @@ class FieldStorage:
+             query = urlparse.parse_qsl(self.qs_on_post,
+                                        self.keep_blank_values,
+                                        self.strict_parsing,
+-                                       self.max_num_fields)
++                                       self.max_num_fields, separator=self.separator)
+             self.list.extend(MiniFieldStorage(key, value)
+                              for key, value in query)
+             FieldStorageClass = None
+diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py
+index 743c2af..f414faa 100644
+--- a/Lib/test/test_cgi.py
++++ b/Lib/test/test_cgi.py
+@@ -61,12 +61,9 @@ parse_strict_test_cases = [
+     ("", ValueError("bad query field: ''")),
+     ("&", ValueError("bad query field: ''")),
+     ("&&", ValueError("bad query field: ''")),
+-    (";", ValueError("bad query field: ''")),
+-    (";&;", ValueError("bad query field: ''")),
+     # Should the next few really be valid?
+     ("=", {}),
+     ("=&=", {}),
+-    ("=;=", {}),
+     # This rest seem to make sense
+     ("=a", {'': ['a']}),
+     ("&=a", ValueError("bad query field: ''")),
+@@ -81,8 +78,6 @@ parse_strict_test_cases = [
+     ("a=a+b&b=b+c", {'a': ['a b'], 'b': ['b c']}),
+     ("a=a+b&a=b+a", {'a': ['a b', 'b a']}),
+     ("x=1&y=2.0&z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}),
+-    ("x=1;y=2.0&z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}),
+-    ("x=1;y=2.0;z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}),
+     ("Hbc5161168c542333633315dee1182227:key_store_seqid=400006&cuyer=r&view=bustomer&order_id=0bb2e248638833d48cb7fed300000f1b&expire=964546263&lobale=en-US&kid=130003.300038&ss=env",
+      {'Hbc5161168c542333633315dee1182227:key_store_seqid': ['400006'],
+       'cuyer': ['r'],
+@@ -188,6 +183,30 @@ class CgiTests(unittest.TestCase):
+             self.assertEqual(expect[k], v)
+         self.assertItemsEqual(expect.values(), d.values())
+ 
++    def test_separator(self):
++        parse_semicolon = [
++            ("x=1;y=2.0", {'x': ['1'], 'y': ['2.0']}),
++            ("x=1;y=2.0;z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}),
++            (";", ValueError("bad query field: ''")),
++            (";;", ValueError("bad query field: ''")),
++            ("=;a", ValueError("bad query field: 'a'")),
++            (";b=a", ValueError("bad query field: ''")),
++            ("b;=a", ValueError("bad query field: 'b'")),
++            ("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}),
++            ("a=a+b;a=b+a", {'a': ['a b', 'b a']}),
++        ]
++        for orig, expect in parse_semicolon:
++            env = {'QUERY_STRING': orig}
++            fs = cgi.FieldStorage(separator=';', environ=env)
++            if isinstance(expect, dict):
++                for key in expect.keys():
++                    expect_val = expect[key]
++                    self.assertIn(key, fs)
++                    if len(expect_val) > 1:
++                        self.assertEqual(fs.getvalue(key), expect_val)
++                    else:
++                        self.assertEqual(fs.getvalue(key), expect_val[0])
++
+     def test_log(self):
+         cgi.log("Testing")
+ 
+diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
+index 86c4a05..d729546 100644
+--- a/Lib/test/test_urlparse.py
++++ b/Lib/test/test_urlparse.py
+@@ -24,16 +24,10 @@ parse_qsl_test_cases = [
+     ("&a=b", [('a', 'b')]),
+     ("a=a+b&b=b+c", [('a', 'a b'), ('b', 'b c')]),
+     ("a=1&a=2", [('a', '1'), ('a', '2')]),
+-    (";", []),
+-    (";;", []),
+-    (";a=b", [('a', 'b')]),
+-    ("a=a+b;b=b+c", [('a', 'a b'), ('b', 'b c')]),
+-    ("a=1;a=2", [('a', '1'), ('a', '2')]),
+-    (b";", []),
+-    (b";;", []),
+-    (b";a=b", [(b'a', b'b')]),
+-    (b"a=a+b;b=b+c", [(b'a', b'a b'), (b'b', b'b c')]),
+-    (b"a=1;a=2", [(b'a', b'1'), (b'a', b'2')]),
++    (";a=b", [(';a', 'b')]),
++    ("a=a+b;b=b+c", [('a', 'a b;b=b c')]),
++    (b";a=b", [(b';a', b'b')]),
++    (b"a=a+b;b=b+c", [(b'a', b'a b;b=b c')]),
+ ]
+ 
+ parse_qs_test_cases = [
+@@ -57,16 +51,10 @@ parse_qs_test_cases = [
+     (b"&a=b", {b'a': [b'b']}),
+     (b"a=a+b&b=b+c", {b'a': [b'a b'], b'b': [b'b c']}),
+     (b"a=1&a=2", {b'a': [b'1', b'2']}),
+-    (";", {}),
+-    (";;", {}),
+-    (";a=b", {'a': ['b']}),
+-    ("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}),
+-    ("a=1;a=2", {'a': ['1', '2']}),
+-    (b";", {}),
+-    (b";;", {}),
+-    (b";a=b", {b'a': [b'b']}),
+-    (b"a=a+b;b=b+c", {b'a': [b'a b'], b'b': [b'b c']}),
+-    (b"a=1;a=2", {b'a': [b'1', b'2']}),
++    (";a=b", {';a': ['b']}),
++    ("a=a+b;b=b+c", {'a': ['a b;b=b c']}),
++    (b";a=b", {b';a': [b'b']}),
++    (b"a=a+b;b=b+c", {b'a':[ b'a b;b=b c']}),
+ ]
+ 
+ class UrlParseTestCase(unittest.TestCase):
+@@ -617,6 +605,43 @@ class UrlParseTestCase(unittest.TestCase):
+         self.assertEqual(urlparse.urlparse("http://www.python.org:80"),
+                 ('http','www.python.org:80','','','',''))
+ 
++    def test_parse_qs_separator(self):
++        parse_qs_semicolon_cases = [
++            (";", {}),
++            (";;", {}),
++            (";a=b", {'a': ['b']}),
++            ("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}),
++            ("a=1;a=2", {'a': ['1', '2']}),
++            (b";", {}),
++            (b";;", {}),
++            (b";a=b", {b'a': [b'b']}),
++            (b"a=a+b;b=b+c", {b'a': [b'a b'], b'b': [b'b c']}),
++            (b"a=1;a=2", {b'a': [b'1', b'2']}),
++        ]
++        for orig, expect in parse_qs_semicolon_cases:
++            print("Original: %s, Expected: %s"%(orig, expect))
++            result = urlparse.parse_qs(orig, separator=';')
++            self.assertEqual(result, expect, "Error parsing %r" % orig)
++
++
++    def test_parse_qsl_separator(self):
++        parse_qsl_semicolon_cases = [
++            (";", []),
++            (";;", []),
++            (";a=b", [('a', 'b')]),
++            ("a=a+b;b=b+c", [('a', 'a b'), ('b', 'b c')]),
++            ("a=1;a=2", [('a', '1'), ('a', '2')]),
++            (b";", []),
++            (b";;", []),
++            (b";a=b", [(b'a', b'b')]),
++            (b"a=a+b;b=b+c", [(b'a', b'a b'), (b'b', b'b c')]),
++            (b"a=1;a=2", [(b'a', b'1'), (b'a', b'2')]),
++        ]
++        for orig, expect in parse_qsl_semicolon_cases:
++            print("Original: %s, Expected: %s"%(orig, expect))
++            result = urlparse.parse_qsl(orig, separator=';')
++            self.assertEqual(result, expect, "Error parsing %r" % orig)
++
+     def test_portseparator(self):
+         # Issue 754016 makes changes for port separator ':' from scheme separator
+         self.assertEqual(urlparse.urlparse("path:80"),
+diff --git a/Lib/urlparse.py b/Lib/urlparse.py
+index 798b467..82d8e7e 100644
+--- a/Lib/urlparse.py
++++ b/Lib/urlparse.py
+@@ -382,7 +382,7 @@ def unquote(s):
+             append(item)
+     return ''.join(res)
+ 
+-def parse_qs(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None):
++def parse_qs(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None, separator='&'):
+     """Parse a query given as a string argument.
+ 
+         Arguments:
+@@ -402,17 +402,21 @@ def parse_qs(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None):
+ 
+         max_num_fields: int. If set, then throws a ValueError if there
+             are more than n fields read by parse_qsl().
++
++        separator: str. The symbol to use for separating the query arguments.
++            Defaults to &.
++
+     """
+     dict = {}
+     for name, value in parse_qsl(qs, keep_blank_values, strict_parsing,
+-                                 max_num_fields):
++                                 max_num_fields, separator=separator):
+         if name in dict:
+             dict[name].append(value)
+         else:
+             dict[name] = [value]
+     return dict
+ 
+-def parse_qsl(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None):
++def parse_qsl(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None, separator='&'):
+     """Parse a query given as a string argument.
+ 
+     Arguments:
+@@ -431,6 +435,8 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None):
+ 
+     max_num_fields: int. If set, then throws a ValueError if there
+         are more than n fields read by parse_qsl().
++    separator: str. The symbol to use for separating the query arguments.
++        Defaults to &.
+ 
+     Returns a list, as G-d intended.
+     """
+@@ -442,7 +448,12 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0, max_num_fields=None):
+         if max_num_fields < num_fields:
+             raise ValueError('Max number of fields exceeded')
+ 
+-    pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
++    if not separator or (not isinstance(separator, str)
++        and not isinstance(separator, bytes)):
++        raise ValueError("Separator must be of type string or bytes.")
++
++    pairs = [s1 for s1 in qs.split(separator)]
++
+     r = []
+     for name_value in pairs:
+         if not name_value and not strict_parsing:
diff -pruN 2.7.18-13/debian/patches/CVE-2021-4189.patch 2.7.18-13.2/debian/patches/CVE-2021-4189.patch
--- 2.7.18-13/debian/patches/CVE-2021-4189.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.7.18-13.2/debian/patches/CVE-2021-4189.patch	2022-08-01 09:11:46.000000000 +0000
@@ -0,0 +1,85 @@
+Description:CVE-2021-4189
+Origin: https://github.com/python/cpython/commit/0ab152c6b5d95caa2dc1a30fa96e10258b5f188e
+
+Index: python2.7/Lib/ftplib.py
+===================================================================
+--- python2.7.orig/Lib/ftplib.py
++++ python2.7/Lib/ftplib.py
+@@ -107,7 +107,9 @@ class FTP:
+     sock = None
+     file = None
+     welcome = None
+-    passiveserver = 1
++    passiveserver = True
++    # Disables https://bugs.python.org/issue43285 security if set to True.
++    trust_server_pasv_ipv4_address = False
+ 
+     # Initialization method (called by class instantiation).
+     # Initialize host to localhost, port to standard ftp port
+@@ -310,8 +312,13 @@ class FTP:
+         return sock
+ 
+     def makepasv(self):
++        """Internal: Does the PASV or EPSV handshake -> (address, port)"""
+         if self.af == socket.AF_INET:
+-            host, port = parse227(self.sendcmd('PASV'))
++            untrusted_host, port = parse227(self.sendcmd('PASV'))
++            if self.trust_server_pasv_ipv4_address:
++                host = untrusted_host
++            else:
++                host = self.sock.getpeername()[0]
+         else:
+             host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
+         return host, port
+Index: python2.7/Lib/test/test_ftplib.py
+===================================================================
+--- python2.7.orig/Lib/test/test_ftplib.py
++++ python2.7/Lib/test/test_ftplib.py
+@@ -67,6 +67,10 @@ class DummyFTPHandler(asynchat.async_cha
+         self.rest = None
+         self.next_retr_data = RETR_DATA
+         self.push('220 welcome')
++        # We use this as the string IPv4 address to direct the client
++        # to in response to a PASV command.  To test security behavior.
++        # https://bugs.python.org/issue43285/.
++        self.fake_pasv_server_ip = '252.253.254.255'
+ 
+     def collect_incoming_data(self, data):
+         self.in_buffer.append(data)
+@@ -109,7 +113,8 @@ class DummyFTPHandler(asynchat.async_cha
+         sock.bind((self.socket.getsockname()[0], 0))
+         sock.listen(5)
+         sock.settimeout(10)
+-        ip, port = sock.getsockname()[:2]
++        port = sock.getsockname()[1]
++        ip = self.fake_pasv_server_ip
+         ip = ip.replace('.', ',')
+         p1, p2 = divmod(port, 256)
+         self.push('227 entering passive mode (%s,%d,%d)' %(ip, p1, p2))
+@@ -570,6 +575,26 @@ class TestFTPClass(TestCase):
+         # IPv4 is in use, just make sure send_eprt has not been used
+         self.assertEqual(self.server.handler_instance.last_received_cmd, 'port')
+ 
++    def test_makepasv_issue43285_security_disabled(self):
++        """Test the opt-in to the old vulnerable behavior."""
++        self.client.trust_server_pasv_ipv4_address = True
++        bad_host, port = self.client.makepasv()
++        self.assertEqual(
++                bad_host, self.server.handler_instance.fake_pasv_server_ip)
++        # Opening and closing a connection keeps the dummy server happy
++        # instead of timing out on accept.
++        socket.create_connection((self.client.sock.getpeername()[0], port),
++                                 timeout=TIMEOUT).close()
++
++    def test_makepasv_issue43285_security_enabled_default(self):
++        self.assertFalse(self.client.trust_server_pasv_ipv4_address)
++        trusted_host, port = self.client.makepasv()
++        self.assertNotEqual(
++                trusted_host, self.server.handler_instance.fake_pasv_server_ip)
++        # Opening and closing a connection keeps the dummy server happy
++        # instead of timing out on accept.
++        socket.create_connection((trusted_host, port), timeout=TIMEOUT).close()
++
+     def test_makepasv(self):
+         host, port = self.client.makepasv()
+         conn = socket.create_connection((host, port), 10)
diff -pruN 2.7.18-13/debian/patches/disable-sem-check.diff 2.7.18-13.2/debian/patches/disable-sem-check.diff
--- 2.7.18-13/debian/patches/disable-sem-check.diff	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/patches/disable-sem-check.diff	2022-08-01 09:11:46.000000000 +0000
@@ -1,8 +1,10 @@
 # DP: Assume working semaphores on Linux, don't rely on running kernel for the check.
 
---- a/configure.ac
-+++ b/configure.ac
-@@ -4061,6 +4061,11 @@ int main(void) {
+Index: python2.7/configure.ac
+===================================================================
+--- python2.7.orig/configure.ac
++++ python2.7/configure.ac
+@@ -4064,6 +4064,11 @@ int main(void) {
  [ac_cv_posix_semaphores_enabled=no],
  [ac_cv_posix_semaphores_enabled=yes])
  )
@@ -14,7 +16,7 @@
  AC_MSG_RESULT($ac_cv_posix_semaphores_enabled)
  if test $ac_cv_posix_semaphores_enabled = no
  then
-@@ -4097,6 +4102,11 @@ int main(void){
+@@ -4100,6 +4105,11 @@ int main(void){
  [ac_cv_broken_sem_getvalue=yes],
  [ac_cv_broken_sem_getvalue=yes])
  )
diff -pruN 2.7.18-13/debian/patches/issue46811.diff 2.7.18-13.2/debian/patches/issue46811.diff
--- 2.7.18-13/debian/patches/issue46811.diff	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/patches/issue46811.diff	2022-08-01 09:11:46.000000000 +0000
@@ -1,6 +1,8 @@
---- a/Lib/test/test_minidom.py
-+++ b/Lib/test/test_minidom.py
-@@ -6,12 +6,14 @@
+Index: python2.7/Lib/test/test_minidom.py
+===================================================================
+--- python2.7.orig/Lib/test/test_minidom.py
++++ python2.7/Lib/test/test_minidom.py
+@@ -6,12 +6,14 @@ from StringIO import StringIO
  from test import support
  import unittest
  
@@ -15,7 +17,7 @@
  
  
  tstfile = support.findfile("test.xml", subdir="xmltestdata")
-@@ -1051,7 +1053,13 @@
+@@ -1051,7 +1053,13 @@ class MinidomTest(unittest.TestCase):
  
          # Verify that character decoding errors raise exceptions instead
          # of crashing
@@ -30,9 +32,11 @@
                  '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
  
          doc.unlink()
---- a/Lib/test/test_xml_etree.py
-+++ b/Lib/test/test_xml_etree.py
-@@ -1683,12 +1683,6 @@ def test_issue6233(self):
+Index: python2.7/Lib/test/test_xml_etree.py
+===================================================================
+--- python2.7.orig/Lib/test/test_xml_etree.py
++++ python2.7/Lib/test/test_xml_etree.py
+@@ -1482,12 +1482,6 @@ class BugsTest(unittest.TestCase):
                  b"<?xml version='1.0' encoding='ascii'?>\n"
                  b'<body>t&#227;g</body>')
  
diff -pruN 2.7.18-13/debian/patches/local-doc-references.diff 2.7.18-13.2/debian/patches/local-doc-references.diff
--- 2.7.18-13/debian/patches/local-doc-references.diff	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/patches/local-doc-references.diff	2022-08-01 09:11:46.000000000 +0000
@@ -1,8 +1,8 @@
-Index: b/Doc/tools/templates/layout.html
+Index: python2.7/Doc/tools/templates/layout.html
 ===================================================================
---- a/Doc/tools/templates/layout.html
-+++ b/Doc/tools/templates/layout.html
-@@ -17,7 +17,7 @@
+--- python2.7.orig/Doc/tools/templates/layout.html
++++ python2.7/Doc/tools/templates/layout.html
+@@ -27,7 +27,7 @@
  {% block relbar2 %} {% if builder != 'qthelp' %} {{ relbar() }} {% endif %} {% endblock %}
  {% block extrahead %}
      <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/py.png', 1) }}" />
@@ -11,10 +11,10 @@ Index: b/Doc/tools/templates/layout.html
      {% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %}
      {% if switchers is defined and not embedded %}<script type="text/javascript" src="{{ pathto('_static/switchers.js', 1) }}"></script>{% endif %}
  {{ super() }}
-Index: b/Misc/python.man
+Index: python2.7/Misc/python.man
 ===================================================================
---- a/Misc/python.man
-+++ b/Misc/python.man
+--- python2.7.orig/Misc/python.man
++++ python2.7/Misc/python.man
 @@ -456,7 +456,8 @@ The Python Software Foundation: https://
  .SH INTERNET RESOURCES
  Main website:  https://www.python.org/
diff -pruN 2.7.18-13/debian/patches/series.in 2.7.18-13.2/debian/patches/series.in
--- 2.7.18-13/debian/patches/series.in	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/patches/series.in	2022-08-01 09:11:46.000000000 +0000
@@ -84,3 +84,4 @@ openssl3-tests-tlsv1.diff
 sphinx4.diff
 skip-tls1.2-tests.diff
 issue46811.diff
+CVE-2021-4189.patch
diff -pruN 2.7.18-13/debian/patches/skip-tls1.2-tests.diff 2.7.18-13.2/debian/patches/skip-tls1.2-tests.diff
--- 2.7.18-13/debian/patches/skip-tls1.2-tests.diff	2022-08-01 09:11:45.000000000 +0000
+++ 2.7.18-13.2/debian/patches/skip-tls1.2-tests.diff	2022-08-01 09:11:46.000000000 +0000
@@ -1,5 +1,7 @@
---- a/Lib/test/test_ssl.py
-+++ b/Lib/test/test_ssl.py
+Index: python2.7/Lib/test/test_ssl.py
+===================================================================
+--- python2.7.orig/Lib/test/test_ssl.py
++++ python2.7/Lib/test/test_ssl.py
 @@ -29,6 +29,7 @@ PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
  HOST = support.HOST
  IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL')
@@ -8,7 +10,7 @@
  
  
  def data_file(*name):
-@@ -172,6 +173,8 @@ def skip_if_openssl_cnf_minprotocol_gt_tls11(func):
+@@ -171,6 +172,8 @@ def skip_if_openssl_cnf_minprotocol_gt_t
      """
      @functools.wraps(func)
      def f(*args, **kwargs):
