all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#46631: Python CVE-2021-3177
@ 2021-02-19  3:21 Leo Famulari
  2021-02-19 15:35 ` Ludovic Courtès
  2021-02-19 23:12 ` Leo Famulari
  0 siblings, 2 replies; 7+ messages in thread
From: Leo Famulari @ 2021-02-19  3:21 UTC (permalink / raw)
  To: 46631

Quoting from MITRE:

------
Python 3.x through 3.9.1 has a buffer overflow in PyCArg_repr in
_ctypes/callproc.c, which may lead to remote code execution in certain
Python applications that accept floating-point numbers as untrusted
input, as demonstrated by a 1e300 argument to c_double.from_param. This
occurs because sprintf is used unsafely. 
------
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3177

There is not yet an upstream release to fix the issue in the 3.8 series
that we distribute. I believe there are patches we can cherry-pick. Can
somebody find them?

I assume that Python is considered to be "graft-able". Can anyone
confirm?

The upstream bug report:
https://bugs.python.org/issue42938




^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#46631: Python CVE-2021-3177
  2021-02-19  3:21 bug#46631: Python CVE-2021-3177 Leo Famulari
@ 2021-02-19 15:35 ` Ludovic Courtès
  2021-02-19 23:12 ` Leo Famulari
  1 sibling, 0 replies; 7+ messages in thread
From: Ludovic Courtès @ 2021-02-19 15:35 UTC (permalink / raw)
  To: Leo Famulari; +Cc: 46631

Hi,

Leo Famulari <leo@famulari.name> skribis:

> I assume that Python is considered to be "graft-able". Can anyone
> confirm?

Yes, I think so.

Ludo’.




^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#46631: Python CVE-2021-3177
  2021-02-19  3:21 bug#46631: Python CVE-2021-3177 Leo Famulari
  2021-02-19 15:35 ` Ludovic Courtès
@ 2021-02-19 23:12 ` Leo Famulari
  2021-02-19 23:23   ` Leo Famulari
  1 sibling, 1 reply; 7+ messages in thread
From: Leo Famulari @ 2021-02-19 23:12 UTC (permalink / raw)
  To: 46631

[-- Attachment #1: Type: text/plain, Size: 298 bytes --]

I pushed a fix for Python 3.9 in commit
f08c7cb0c75e7d5305c82d6a4af68ddf74fb08b1.

But, we use Python 3.8 for everything, and my patch (attached) fails to
apply for some reason. It does work when I apply the new bug fix patch
"by hand" onto the Guix source code for our current python-3.8 package.

[-- Attachment #2: 0001-gnu-Python-Fix-CVE-2021-3177.patch --]
[-- Type: text/plain, Size: 10262 bytes --]

From 3cc80457d26c725da61307755716db18ff88d28e Mon Sep 17 00:00:00 2001
From: Leo Famulari <leo@famulari.name>
Date: Fri, 19 Feb 2021 18:09:57 -0500
Subject: [PATCH] gnu: Python: Fix CVE-2021-3177.

* gnu/packages/patches/python-3.8-CVE-2021-3177.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
* gnu/packages/python.scm (python-3.8)[replacement]: New field.
(python-3.8/fixed): New variable.
---
 gnu/local.mk                                  |   1 +
 .../patches/python-3.8-CVE-2021-3177.patch    | 194 ++++++++++++++++++
 gnu/packages/python.scm                       |   8 +
 3 files changed, 203 insertions(+)
 create mode 100644 gnu/packages/patches/python-3.8-CVE-2021-3177.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 5588cda2e1..26dbcb940f 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1526,6 +1526,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/python-3-search-paths.patch		\
   %D%/packages/patches/python-3-fix-tests.patch			\
   %D%/packages/patches/python-3.8-fix-tests.patch		\
+  %D%/packages/patches/python-3.8-CVE-2021-3177.patch		\
   %D%/packages/patches/python-3.9-fix-tests.patch		\
   %D%/packages/patches/python-3.9-CVE-2021-3177.patch		\
   %D%/packages/patches/python-CVE-2018-14647.patch		\
diff --git a/gnu/packages/patches/python-3.8-CVE-2021-3177.patch b/gnu/packages/patches/python-3.8-CVE-2021-3177.patch
new file mode 100644
index 0000000000..01f6b52865
--- /dev/null
+++ b/gnu/packages/patches/python-3.8-CVE-2021-3177.patch
@@ -0,0 +1,194 @@
+Fix CVE-2021-3177 for Python 3.8:
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3177
+
+Patch copied from upstream source repository:
+
+https://github.com/python/cpython/commit/ece5dfd403dac211f8d3c72701fe7ba7b7aa5b5f
+
+From ece5dfd403dac211f8d3c72701fe7ba7b7aa5b5f Mon Sep 17 00:00:00 2001
+From: "Miss Islington (bot)"
+ <31488909+miss-islington@users.noreply.github.com>
+Date: Mon, 18 Jan 2021 13:28:52 -0800
+Subject: [PATCH] closes bpo-42938: Replace snprintf with Python unicode
+ formatting in ctypes param reprs. (GH-24248)
+
+(cherry picked from commit 916610ef90a0d0761f08747f7b0905541f0977c7)
+
+Co-authored-by: Benjamin Peterson <benjamin@python.org>
+
+Co-authored-by: Benjamin Peterson <benjamin@python.org>
+---
+ Lib/ctypes/test/test_parameters.py            | 43 ++++++++++++++++
+ .../2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst  |  2 +
+ Modules/_ctypes/callproc.c                    | 51 +++++++------------
+ 3 files changed, 64 insertions(+), 32 deletions(-)
+ create mode 100644 Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst
+
+diff --git a/Lib/ctypes/test/test_parameters.py b/Lib/ctypes/test/test_parameters.py
+index e4c25fd880cef..531894fdec838 100644
+--- a/Lib/ctypes/test/test_parameters.py
++++ b/Lib/ctypes/test/test_parameters.py
+@@ -201,6 +201,49 @@ def __dict__(self):
+         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.assertRegex(repr(c_bool.from_param(True)), r"^<cparam '\?' at 0x[A-Fa-f0-9]+>$")
++        self.assertEqual(repr(c_char.from_param(97)), "<cparam 'c' ('a')>")
++        self.assertRegex(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.assertRegex(repr(c_int.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
++        self.assertRegex(repr(c_uint.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
++        self.assertRegex(repr(c_long.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
++        self.assertRegex(repr(c_ulong.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
++        self.assertRegex(repr(c_longlong.from_param(20000)), r"^<cparam '[liq]' \(20000\)>$")
++        self.assertRegex(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.assertRegex(repr(c_longdouble.from_param(1.5)), r"^<cparam ('d' \(1.5\)|'g' at 0x[A-Fa-f0-9]+)>$")
++        self.assertRegex(repr(c_char_p.from_param(b'hihi')), "^<cparam 'z' \(0x[A-Fa-f0-9]+\)>$")
++        self.assertRegex(repr(c_wchar_p.from_param('hihi')), "^<cparam 'Z' \(0x[A-Fa-f0-9]+\)>$")
++        self.assertRegex(repr(c_void_p.from_param(0x12)), r"^<cparam 'P' \(0x0*12\)>$")
++
+ ################################################################
+ 
+ if __name__ == '__main__':
+#diff --git a/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst b/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst
+#new file mode 100644
+#index 0000000000000..7df65a156feab
+#--- /dev/null
+#+++ b/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst
+#@@ -0,0 +1,2 @@
+#+Avoid static buffers when computing the repr of :class:`ctypes.c_double` and
+#+:class:`ctypes.c_longdouble` values.
+diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
+index a9b8675cd951b..de75918d49f37 100644
+--- a/Modules/_ctypes/callproc.c
++++ b/Modules/_ctypes/callproc.c
+@@ -484,58 +484,47 @@ is_literal_char(unsigned char c)
+ static PyObject *
+ PyCArg_repr(PyCArgObject *self)
+ {
+-    char buffer[256];
+     switch(self->tag) {
+     case 'b':
+     case 'B':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.b);
+-        break;
+     case 'h':
+     case 'H':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.h);
+-        break;
+     case 'i':
+     case 'I':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.i);
+-        break;
+     case 'l':
+     case 'L':
+-        sprintf(buffer, "<cparam '%c' (%ld)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%ld)>",
+             self->tag, self->value.l);
+-        break;
+ 
+     case 'q':
+     case 'Q':
+-        sprintf(buffer,
+-#ifdef MS_WIN32
+-            "<cparam '%c' (%I64d)>",
+-#else
+-            "<cparam '%c' (%lld)>",
+-#endif
++        return PyUnicode_FromFormat("<cparam '%c' (%lld)>",
+             self->tag, self->value.q);
+-        break;
+     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 *result = PyUnicode_FromFormat("<cparam '%c' (%R)>", self->tag, f);
++        Py_DECREF(f);
++        return result;
++    }
+     case 'c':
+         if (is_literal_char((unsigned char)self->value.c)) {
+-            sprintf(buffer, "<cparam '%c' ('%c')>",
++            return PyUnicode_FromFormat("<cparam '%c' ('%c')>",
+                 self->tag, self->value.c);
+         }
+         else {
+-            sprintf(buffer, "<cparam '%c' ('\\x%02x')>",
++            return PyUnicode_FromFormat("<cparam '%c' ('\\x%02x')>",
+                 self->tag, (unsigned char)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
+@@ -544,22 +533,20 @@ PyCArg_repr(PyCArgObject *self)
+     case 'z':
+     case 'Z':
+     case 'P':
+-        sprintf(buffer, "<cparam '%c' (%p)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%p)>",
+             self->tag, self->value.p);
+         break;
+ 
+     default:
+         if (is_literal_char((unsigned char)self->tag)) {
+-            sprintf(buffer, "<cparam '%c' at %p>",
++            return PyUnicode_FromFormat("<cparam '%c' at %p>",
+                 (unsigned char)self->tag, (void *)self);
+         }
+         else {
+-            sprintf(buffer, "<cparam 0x%02x at %p>",
++            return PyUnicode_FromFormat("<cparam 0x%02x at %p>",
+                 (unsigned char)self->tag, (void *)self);
+         }
+-        break;
+     }
+-    return PyUnicode_FromString(buffer);
+ }
+ 
+ static PyMemberDef PyCArgType_members[] = {
diff --git a/gnu/packages/python.scm b/gnu/packages/python.scm
index 730c371fda..bcf1bfd706 100644
--- a/gnu/packages/python.scm
+++ b/gnu/packages/python.scm
@@ -364,6 +364,7 @@ data types.")
 (define-public python-3.8
   (package (inherit python-2)
     (name "python")
+    (replacement python-3.8/fixed)
     (version "3.8.2")
     (source (origin
               (method url-fetch)
@@ -521,6 +522,13 @@ data types.")
                                         (version-major+minor version)
                                         "/site-packages"))))))))
 
+(define-public python-3.8/fixed
+  (package/inherit python-3.8
+    (source (origin
+              (inherit (package-source python-3.8))
+              (patches (append (search-patches "python-3.8-CVE-2021-3177.patch")
+                               (origin-patches (package-source python-3.8))))))))
+
 (define-public python-3.9
   (package (inherit python-3.8)
     (name "python-next")
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* bug#46631: Python CVE-2021-3177
  2021-02-19 23:12 ` Leo Famulari
@ 2021-02-19 23:23   ` Leo Famulari
  2021-02-19 23:41     ` Leo Famulari
  0 siblings, 1 reply; 7+ messages in thread
From: Leo Famulari @ 2021-02-19 23:23 UTC (permalink / raw)
  To: 46631

On Fri, Feb 19, 2021 at 06:12:58PM -0500, Leo Famulari wrote:
> But, we use Python 3.8 for everything, and my patch (attached) fails to
> apply for some reason. It does work when I apply the new bug fix patch
> "by hand" onto the Guix source code for our current python-3.8 package.

More weirdness: When I apply the patch to the python-3.8 package (that
is, without setting up a grafted replacement), it works. So I am
definitely doing something wrong here.




^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#46631: Python CVE-2021-3177
  2021-02-19 23:23   ` Leo Famulari
@ 2021-02-19 23:41     ` Leo Famulari
  2021-02-22  8:08       ` Ludovic Courtès
  0 siblings, 1 reply; 7+ messages in thread
From: Leo Famulari @ 2021-02-19 23:41 UTC (permalink / raw)
  To: 46631


[-- Attachment #1.1: Type: text/plain, Size: 374 bytes --]

On Fri, Feb 19, 2021 at 06:23:49PM -0500, Leo Famulari wrote:
> More weirdness: When I apply the patch to the python-3.8 package (that
> is, without setting up a grafted replacement), it works. So I am
> definitely doing something wrong here.

Here is a new patch that I'm currently building. I think I had composed
the package inheritance incorrectly in my previous patch.

[-- Attachment #1.2: 0001-gnu-Python-Fix-CVE-2021-3177.patch --]
[-- Type: text/plain, Size: 10650 bytes --]

From b62969d52add462fc1b8b4bd1e0a3c4d53a39864 Mon Sep 17 00:00:00 2001
From: Leo Famulari <leo@famulari.name>
Date: Fri, 19 Feb 2021 18:09:57 -0500
Subject: [PATCH] gnu: Python: Fix CVE-2021-3177.

* gnu/packages/patches/python-3.8-CVE-2021-3177.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
* gnu/packages/python.scm (python-3.8): Define with PACKAGE/INHERIT.
[replacement]: New field.
(python-3.8/fixed): New variable.
---
 gnu/local.mk                                  |   1 +
 .../patches/python-3.8-CVE-2021-3177.patch    | 194 ++++++++++++++++++
 gnu/packages/python.scm                       |  11 +-
 3 files changed, 205 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/python-3.8-CVE-2021-3177.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 5588cda2e1..26dbcb940f 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1526,6 +1526,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/python-3-search-paths.patch		\
   %D%/packages/patches/python-3-fix-tests.patch			\
   %D%/packages/patches/python-3.8-fix-tests.patch		\
+  %D%/packages/patches/python-3.8-CVE-2021-3177.patch		\
   %D%/packages/patches/python-3.9-fix-tests.patch		\
   %D%/packages/patches/python-3.9-CVE-2021-3177.patch		\
   %D%/packages/patches/python-CVE-2018-14647.patch		\
diff --git a/gnu/packages/patches/python-3.8-CVE-2021-3177.patch b/gnu/packages/patches/python-3.8-CVE-2021-3177.patch
new file mode 100644
index 0000000000..01f6b52865
--- /dev/null
+++ b/gnu/packages/patches/python-3.8-CVE-2021-3177.patch
@@ -0,0 +1,194 @@
+Fix CVE-2021-3177 for Python 3.8:
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3177
+
+Patch copied from upstream source repository:
+
+https://github.com/python/cpython/commit/ece5dfd403dac211f8d3c72701fe7ba7b7aa5b5f
+
+From ece5dfd403dac211f8d3c72701fe7ba7b7aa5b5f Mon Sep 17 00:00:00 2001
+From: "Miss Islington (bot)"
+ <31488909+miss-islington@users.noreply.github.com>
+Date: Mon, 18 Jan 2021 13:28:52 -0800
+Subject: [PATCH] closes bpo-42938: Replace snprintf with Python unicode
+ formatting in ctypes param reprs. (GH-24248)
+
+(cherry picked from commit 916610ef90a0d0761f08747f7b0905541f0977c7)
+
+Co-authored-by: Benjamin Peterson <benjamin@python.org>
+
+Co-authored-by: Benjamin Peterson <benjamin@python.org>
+---
+ Lib/ctypes/test/test_parameters.py            | 43 ++++++++++++++++
+ .../2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst  |  2 +
+ Modules/_ctypes/callproc.c                    | 51 +++++++------------
+ 3 files changed, 64 insertions(+), 32 deletions(-)
+ create mode 100644 Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst
+
+diff --git a/Lib/ctypes/test/test_parameters.py b/Lib/ctypes/test/test_parameters.py
+index e4c25fd880cef..531894fdec838 100644
+--- a/Lib/ctypes/test/test_parameters.py
++++ b/Lib/ctypes/test/test_parameters.py
+@@ -201,6 +201,49 @@ def __dict__(self):
+         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.assertRegex(repr(c_bool.from_param(True)), r"^<cparam '\?' at 0x[A-Fa-f0-9]+>$")
++        self.assertEqual(repr(c_char.from_param(97)), "<cparam 'c' ('a')>")
++        self.assertRegex(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.assertRegex(repr(c_int.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
++        self.assertRegex(repr(c_uint.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
++        self.assertRegex(repr(c_long.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
++        self.assertRegex(repr(c_ulong.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
++        self.assertRegex(repr(c_longlong.from_param(20000)), r"^<cparam '[liq]' \(20000\)>$")
++        self.assertRegex(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.assertRegex(repr(c_longdouble.from_param(1.5)), r"^<cparam ('d' \(1.5\)|'g' at 0x[A-Fa-f0-9]+)>$")
++        self.assertRegex(repr(c_char_p.from_param(b'hihi')), "^<cparam 'z' \(0x[A-Fa-f0-9]+\)>$")
++        self.assertRegex(repr(c_wchar_p.from_param('hihi')), "^<cparam 'Z' \(0x[A-Fa-f0-9]+\)>$")
++        self.assertRegex(repr(c_void_p.from_param(0x12)), r"^<cparam 'P' \(0x0*12\)>$")
++
+ ################################################################
+ 
+ if __name__ == '__main__':
+#diff --git a/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst b/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst
+#new file mode 100644
+#index 0000000000000..7df65a156feab
+#--- /dev/null
+#+++ b/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst
+#@@ -0,0 +1,2 @@
+#+Avoid static buffers when computing the repr of :class:`ctypes.c_double` and
+#+:class:`ctypes.c_longdouble` values.
+diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
+index a9b8675cd951b..de75918d49f37 100644
+--- a/Modules/_ctypes/callproc.c
++++ b/Modules/_ctypes/callproc.c
+@@ -484,58 +484,47 @@ is_literal_char(unsigned char c)
+ static PyObject *
+ PyCArg_repr(PyCArgObject *self)
+ {
+-    char buffer[256];
+     switch(self->tag) {
+     case 'b':
+     case 'B':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.b);
+-        break;
+     case 'h':
+     case 'H':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.h);
+-        break;
+     case 'i':
+     case 'I':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.i);
+-        break;
+     case 'l':
+     case 'L':
+-        sprintf(buffer, "<cparam '%c' (%ld)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%ld)>",
+             self->tag, self->value.l);
+-        break;
+ 
+     case 'q':
+     case 'Q':
+-        sprintf(buffer,
+-#ifdef MS_WIN32
+-            "<cparam '%c' (%I64d)>",
+-#else
+-            "<cparam '%c' (%lld)>",
+-#endif
++        return PyUnicode_FromFormat("<cparam '%c' (%lld)>",
+             self->tag, self->value.q);
+-        break;
+     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 *result = PyUnicode_FromFormat("<cparam '%c' (%R)>", self->tag, f);
++        Py_DECREF(f);
++        return result;
++    }
+     case 'c':
+         if (is_literal_char((unsigned char)self->value.c)) {
+-            sprintf(buffer, "<cparam '%c' ('%c')>",
++            return PyUnicode_FromFormat("<cparam '%c' ('%c')>",
+                 self->tag, self->value.c);
+         }
+         else {
+-            sprintf(buffer, "<cparam '%c' ('\\x%02x')>",
++            return PyUnicode_FromFormat("<cparam '%c' ('\\x%02x')>",
+                 self->tag, (unsigned char)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
+@@ -544,22 +533,20 @@ PyCArg_repr(PyCArgObject *self)
+     case 'z':
+     case 'Z':
+     case 'P':
+-        sprintf(buffer, "<cparam '%c' (%p)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%p)>",
+             self->tag, self->value.p);
+         break;
+ 
+     default:
+         if (is_literal_char((unsigned char)self->tag)) {
+-            sprintf(buffer, "<cparam '%c' at %p>",
++            return PyUnicode_FromFormat("<cparam '%c' at %p>",
+                 (unsigned char)self->tag, (void *)self);
+         }
+         else {
+-            sprintf(buffer, "<cparam 0x%02x at %p>",
++            return PyUnicode_FromFormat("<cparam 0x%02x at %p>",
+                 (unsigned char)self->tag, (void *)self);
+         }
+-        break;
+     }
+-    return PyUnicode_FromString(buffer);
+ }
+ 
+ static PyMemberDef PyCArgType_members[] = {
diff --git a/gnu/packages/python.scm b/gnu/packages/python.scm
index 730c371fda..fc28d0e3f8 100644
--- a/gnu/packages/python.scm
+++ b/gnu/packages/python.scm
@@ -362,8 +362,9 @@ data types.")
     (properties `((superseded . ,python-2)))))
 
 (define-public python-3.8
-  (package (inherit python-2)
+  (package/inherit python-2
     (name "python")
+    (replacement python-3.8/fixed)
     (version "3.8.2")
     (source (origin
               (method url-fetch)
@@ -521,6 +522,14 @@ data types.")
                                         (version-major+minor version)
                                         "/site-packages"))))))))
 
+(define python-3.8/fixed
+  (package
+    (inherit python-3.8)
+    (source (origin
+              (inherit (package-source python-3.8))
+              (patches (append (search-patches "python-3.8-CVE-2021-3177.patch")
+                               (origin-patches (package-source python-3.8))))))))
+
 (define-public python-3.9
   (package (inherit python-3.8)
     (name "python-next")
-- 
2.30.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* bug#46631: Python CVE-2021-3177
  2021-02-19 23:41     ` Leo Famulari
@ 2021-02-22  8:08       ` Ludovic Courtès
  2021-02-23 19:16         ` Leo Famulari
  0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2021-02-22  8:08 UTC (permalink / raw)
  To: Leo Famulari; +Cc: 46631

Hi Leo,

Leo Famulari <leo@famulari.name> skribis:

> From b62969d52add462fc1b8b4bd1e0a3c4d53a39864 Mon Sep 17 00:00:00 2001
> From: Leo Famulari <leo@famulari.name>
> Date: Fri, 19 Feb 2021 18:09:57 -0500
> Subject: [PATCH] gnu: Python: Fix CVE-2021-3177.
>
> * gnu/packages/patches/python-3.8-CVE-2021-3177.patch: New file.
> * gnu/local.mk (dist_patch_DATA): Add it.
> * gnu/packages/python.scm (python-3.8): Define with PACKAGE/INHERIT.
> [replacement]: New field.
> (python-3.8/fixed): New variable.

[...]

>  (define-public python-3.8
> -  (package (inherit python-2)
> +  (package/inherit python-2
>      (name "python")
> +    (replacement python-3.8/fixed)

You can keep (inherit …) because the effect of ‘package/inherit’ is just
to preserve replacements, which is unnecessary here.

Apart from that, the Guix side of things LGTM.

Thanks for working on it!

Ludo’.




^ permalink raw reply	[flat|nested] 7+ messages in thread

* bug#46631: Python CVE-2021-3177
  2021-02-22  8:08       ` Ludovic Courtès
@ 2021-02-23 19:16         ` Leo Famulari
  0 siblings, 0 replies; 7+ messages in thread
From: Leo Famulari @ 2021-02-23 19:16 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 46631-done

On Mon, Feb 22, 2021 at 09:08:14AM +0100, Ludovic Courtès wrote:
> You can keep (inherit …) because the effect of ‘package/inherit’ is just
> to preserve replacements, which is unnecessary here.

I used to know that... it's been a while and I forgot, and had trouble
understanding the package/inherit docstring. So I pushed a commit that I
hope clarifies it.

> Apart from that, the Guix side of things LGTM.

Pushed as 84e082e31706411e7f9c3189a83f8ed0b4016fe7

> Thanks for working on it!

Thanks for the review!




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-02-23 19:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-19  3:21 bug#46631: Python CVE-2021-3177 Leo Famulari
2021-02-19 15:35 ` Ludovic Courtès
2021-02-19 23:12 ` Leo Famulari
2021-02-19 23:23   ` Leo Famulari
2021-02-19 23:41     ` Leo Famulari
2021-02-22  8:08       ` Ludovic Courtès
2021-02-23 19:16         ` Leo Famulari

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.