Package: release.debian.org Severity: normal Tags: buster User: release.debian....@packages.debian.org Usertags: pu X-Debbugs-Cc: d...@debian.org
debdiff below fixes three security issues, which don't warrant a DSA by itself. Update has been tested on a Buster few systems (and verified with the PoCs). Cheers, Moritz diff -u python2.7-2.7.16/debian/changelog python2.7-2.7.16/debian/changelog --- python2.7-2.7.16/debian/changelog +++ python2.7-2.7.16/debian/changelog @@ -1,3 +1,11 @@ +python2.7 (2.7.16-2+deb10u2) buster; urgency=medium + + * CVE-2020-8492 (Closes: #970099) + * CVE-2019-20907 (Closes: #970099) + * CVE-2021-3177 + + -- Moritz Mühlenhoff <j...@debian.org> Wed, 24 Feb 2021 20:33:20 +0200 + python2.7 (2.7.16-2+deb10u1) buster; urgency=medium * CVE-2018-20852 diff -u python2.7-2.7.16/debian/patches/series.in python2.7-2.7.16/debian/patches/series.in --- python2.7-2.7.16/debian/patches/series.in +++ python2.7-2.7.16/debian/patches/series.in @@ -80,0 +81,3 @@ +CVE-2019-20907.diff +CVE-2020-8492.diff +CVE-2021-3177.diff only in patch2: unchanged: --- python2.7-2.7.16.orig/debian/patches/CVE-2019-20907.diff +++ python2.7-2.7.16/debian/patches/CVE-2019-20907.diff @@ -0,0 +1,26 @@ +From 47a2955589bdb1a114d271496ff803ad73f954b8 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-isling...@users.noreply.github.com> +Date: Wed, 15 Jul 2020 05:36:36 -0700 +Subject: [PATCH] bpo-39017: Avoid infinite loop in the tarfile module + (GH-21454) (#21485) + +Avoid infinite loop when reading specially crafted TAR files using the tarfile module +(CVE-2019-20907). +(cherry picked from commit 5a8d121a1f3ef5ad7c105ee378cc79a3eac0c7d4) + +Co-authored-by: Rishi <rishi_de...@mail.com> + +diff --git a/Lib/tarfile.py b/Lib/tarfile.py +index adf91d5..574a6bb 100644 +--- a/Lib/tarfile.py ++++ b/Lib/tarfile.py +@@ -1400,6 +1400,8 @@ class TarInfo(object): + + length, keyword = match.groups() + length = int(length) ++ if length == 0: ++ raise InvalidHeaderError("invalid header") + value = buf[match.end(2) + 1:match.start(1) + length - 1] + + keyword = keyword.decode("utf8") only in patch2: unchanged: --- python2.7-2.7.16.orig/debian/patches/CVE-2020-8492.diff +++ python2.7-2.7.16/debian/patches/CVE-2020-8492.diff @@ -0,0 +1,26 @@ +Backport of 0b297d4ff1c0e4480ad33acae793fbaf4bf015b4, trimmed down to the +fix for CVE-2020-8492 + +Co-Authored-By: Serhiy Storchaka <storch...@gmail.com> +diff --git a/Lib/urllib2.py b/Lib/urllib2.py +index 8b634ad..11a62a4 100644 +--- a/Lib/urllib2.py ++++ b/Lib/urllib2.py +@@ -856,8 +856,15 @@ class AbstractBasicAuthHandler: + + # allow for double- and single-quoted realm values + # (single quotes are a violation of the RFC, but appear in the wild) +- rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+' +- 'realm=(["\']?)([^"\']*)\\2', re.I) ++ rx = re.compile('(?:^|,)' # start of the string or ',' ++ '[ \t]*' # optional whitespaces ++ '([^ \t]+)' # scheme like "Basic" ++ '[ \t]+' # mandatory whitespaces ++ # realm=xxx ++ # realm='xxx' ++ # realm="xxx" ++ 'realm=(["\']?)([^"\']*)\\2', ++ re.I) + + # XXX could pre-emptively send auth info already accepted (RFC 2617, + # end of section 2, and section 1.2 immediately after "credentials" only in patch2: unchanged: --- python2.7-2.7.16.orig/debian/patches/CVE-2021-3177.diff +++ python2.7-2.7.16/debian/patches/CVE-2021-3177.diff @@ -0,0 +1,149 @@ +bpo-42938: Replace snprintf with Python unicode formatting in ctypes param reprs. +--- a/Lib/ctypes/test/test_parameters.py ++++ b/Lib/ctypes/test/test_parameters.py +@@ -206,6 +206,49 @@ + with self.assertRaises(ZeroDivisionError): + WorseStruct().__setstate__({}, b'foo') + ++ def test_parameter_repr(self): ++ from ctypes import ( ++ c_bool, ++ c_char, ++ c_wchar, ++ c_byte, ++ c_ubyte, ++ c_short, ++ c_ushort, ++ c_int, ++ c_uint, ++ c_long, ++ c_ulong, ++ c_longlong, ++ c_ulonglong, ++ c_float, ++ c_double, ++ c_longdouble, ++ c_char_p, ++ c_wchar_p, ++ c_void_p, ++ ) ++ self.assertRegexpMatches(repr(c_bool.from_param(True)), r"^<cparam '\?' at 0x[A-Fa-f0-9]+>$") ++ self.assertEqual(repr(c_char.from_param('a')), "<cparam 'c' (a)>") ++ self.assertRegexpMatches(repr(c_wchar.from_param('a')), r"^<cparam 'u' at 0x[A-Fa-f0-9]+>$") ++ self.assertEqual(repr(c_byte.from_param(98)), "<cparam 'b' (98)>") ++ self.assertEqual(repr(c_ubyte.from_param(98)), "<cparam 'B' (98)>") ++ self.assertEqual(repr(c_short.from_param(511)), "<cparam 'h' (511)>") ++ self.assertEqual(repr(c_ushort.from_param(511)), "<cparam 'H' (511)>") ++ self.assertRegexpMatches(repr(c_int.from_param(20000)), r"^<cparam '[li]' \(20000\)>$") ++ self.assertRegexpMatches(repr(c_uint.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$") ++ self.assertRegexpMatches(repr(c_long.from_param(20000)), r"^<cparam '[li]' \(20000\)>$") ++ self.assertRegexpMatches(repr(c_ulong.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$") ++ self.assertRegexpMatches(repr(c_longlong.from_param(20000)), r"^<cparam '[liq]' \(20000\)>$") ++ self.assertRegexpMatches(repr(c_ulonglong.from_param(20000)), r"^<cparam '[LIQ]' \(20000\)>$") ++ self.assertEqual(repr(c_float.from_param(1.5)), "<cparam 'f' (1.5)>") ++ self.assertEqual(repr(c_double.from_param(1.5)), "<cparam 'd' (1.5)>") ++ self.assertEqual(repr(c_double.from_param(1e300)), "<cparam 'd' (1e+300)>") ++ self.assertRegexpMatches(repr(c_longdouble.from_param(1.5)), r"^<cparam ('d' \(1.5\)|'g' at 0x[A-Fa-f0-9]+)>$") ++ self.assertRegexpMatches(repr(c_char_p.from_param(b'hihi')), "^<cparam 'z' \(0x[A-Fa-f0-9]+\)>$") ++ self.assertRegexpMatches(repr(c_wchar_p.from_param('hihi')), "^<cparam 'Z' \(0x[A-Fa-f0-9]+\)>$") ++ self.assertRegexpMatches(repr(c_void_p.from_param(0x12)), r"^<cparam 'P' \(0x0*12\)>$") ++ + ################################################################ + + if __name__ == '__main__': +--- a/Modules/_ctypes/callproc.c ++++ b/Modules/_ctypes/callproc.c +@@ -460,50 +460,53 @@ + static PyObject * + PyCArg_repr(PyCArgObject *self) + { +- char buffer[256]; + switch(self->tag) { + case 'b': + case 'B': +- sprintf(buffer, "<cparam '%c' (%d)>", ++ return PyString_FromFormat("<cparam '%c' (%d)>", + self->tag, self->value.b); +- break; + case 'h': + case 'H': +- sprintf(buffer, "<cparam '%c' (%d)>", ++ return PyString_FromFormat("<cparam '%c' (%d)>", + self->tag, self->value.h); +- break; + case 'i': + case 'I': +- sprintf(buffer, "<cparam '%c' (%d)>", ++ return PyString_FromFormat("<cparam '%c' (%d)>", + self->tag, self->value.i); +- break; + case 'l': + case 'L': +- sprintf(buffer, "<cparam '%c' (%ld)>", ++ return PyString_FromFormat("<cparam '%c' (%ld)>", + self->tag, self->value.l); +- break; + + #ifdef HAVE_LONG_LONG + case 'q': + case 'Q': +- sprintf(buffer, +- "<cparam '%c' (%" PY_FORMAT_LONG_LONG "d)>", ++ return PyString_FromFormat("<cparam '%c' (%" PY_FORMAT_LONG_LONG "d)>", + self->tag, self->value.q); +- break; + #endif + case 'd': +- sprintf(buffer, "<cparam '%c' (%f)>", +- self->tag, self->value.d); +- break; +- case 'f': +- sprintf(buffer, "<cparam '%c' (%f)>", +- self->tag, self->value.f); +- break; ++ case 'f': { ++ PyObject *f = PyFloat_FromDouble((self->tag == 'f') ? self->value.f : self->value.d); ++ if (f == NULL) { ++ return NULL; ++ } ++ PyObject *r = PyObject_Repr(f); ++ Py_DECREF(f); ++ if (r == NULL) { ++ return NULL; ++ } ++ char *value = PyString_AsString(r); ++ Py_DECREF(r); ++ if (value == NULL) { ++ return NULL; ++ } ++ return PyString_FromFormat("<cparam '%c' (%s)>", ++ self->tag, value); ++ } + + case 'c': +- sprintf(buffer, "<cparam '%c' (%c)>", ++ return PyString_FromFormat("<cparam '%c' (%c)>", + self->tag, self->value.c); +- break; + + /* Hm, are these 'z' and 'Z' codes useful at all? + Shouldn't they be replaced by the functionality of c_string +@@ -512,16 +515,13 @@ + case 'z': + case 'Z': + case 'P': +- sprintf(buffer, "<cparam '%c' (%p)>", ++ return PyString_FromFormat("<cparam '%c' (%p)>", + self->tag, self->value.p); +- break; + + default: +- sprintf(buffer, "<cparam '%c' at %p>", ++ return PyString_FromFormat("<cparam '%c' at %p>", + self->tag, self); +- break; + } +- return PyString_FromString(buffer); + } + + static PyMemberDef PyCArgType_members[] = {