summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/python/python3/CVE-2018-20406.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/python/python3/CVE-2018-20406.patch')
-rw-r--r--meta/recipes-devtools/python/python3/CVE-2018-20406.patch217
1 files changed, 217 insertions, 0 deletions
diff --git a/meta/recipes-devtools/python/python3/CVE-2018-20406.patch b/meta/recipes-devtools/python/python3/CVE-2018-20406.patch
new file mode 100644
index 0000000000..b69e0c4d6b
--- /dev/null
+++ b/meta/recipes-devtools/python/python3/CVE-2018-20406.patch
@@ -0,0 +1,217 @@
1From 3c7fd2b2729e3ebcf7877e7a32b3bbabf907a38d Mon Sep 17 00:00:00 2001
2From: Victor Stinner <vstinner@redhat.com>
3Date: Tue, 26 Feb 2019 01:42:39 +0100
4Subject: [PATCH] closes bpo-34656: Avoid relying on signed overflow in _pickle
5 memos. (GH-9261) (#11869)
6
7(cherry picked from commit a4ae828ee416a66d8c7bf5ee71d653c2cc6a26dd)
8
9CVE: CVE-2018-20406
10Upstream-Status: Backport
11[https://github.com/python/cpython/commit/ef33dd6036aafbd3f06c1d56e2b1a81dae3da63c]
12
13Signed-off-by: Dan Tran <dantran@microsoft.com>
14---
15 Modules/_pickle.c | 63 ++++++++++++++++++++++++-----------------------
16 1 file changed, 32 insertions(+), 31 deletions(-)
17
18diff --git a/Modules/_pickle.c b/Modules/_pickle.c
19index 0f62b1c019..fcb9e87899 100644
20--- a/Modules/_pickle.c
21+++ b/Modules/_pickle.c
22@@ -527,9 +527,9 @@ typedef struct {
23 } PyMemoEntry;
24
25 typedef struct {
26- Py_ssize_t mt_mask;
27- Py_ssize_t mt_used;
28- Py_ssize_t mt_allocated;
29+ size_t mt_mask;
30+ size_t mt_used;
31+ size_t mt_allocated;
32 PyMemoEntry *mt_table;
33 } PyMemoTable;
34
35@@ -573,8 +573,8 @@ typedef struct UnpicklerObject {
36 /* The unpickler memo is just an array of PyObject *s. Using a dict
37 is unnecessary, since the keys are contiguous ints. */
38 PyObject **memo;
39- Py_ssize_t memo_size; /* Capacity of the memo array */
40- Py_ssize_t memo_len; /* Number of objects in the memo */
41+ size_t memo_size; /* Capacity of the memo array */
42+ size_t memo_len; /* Number of objects in the memo */
43
44 PyObject *pers_func; /* persistent_load() method, can be NULL. */
45
46@@ -658,7 +658,6 @@ PyMemoTable_New(void)
47 static PyMemoTable *
48 PyMemoTable_Copy(PyMemoTable *self)
49 {
50- Py_ssize_t i;
51 PyMemoTable *new = PyMemoTable_New();
52 if (new == NULL)
53 return NULL;
54@@ -675,7 +674,7 @@ PyMemoTable_Copy(PyMemoTable *self)
55 PyErr_NoMemory();
56 return NULL;
57 }
58- for (i = 0; i < self->mt_allocated; i++) {
59+ for (size_t i = 0; i < self->mt_allocated; i++) {
60 Py_XINCREF(self->mt_table[i].me_key);
61 }
62 memcpy(new->mt_table, self->mt_table,
63@@ -721,7 +720,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
64 {
65 size_t i;
66 size_t perturb;
67- size_t mask = (size_t)self->mt_mask;
68+ size_t mask = self->mt_mask;
69 PyMemoEntry *table = self->mt_table;
70 PyMemoEntry *entry;
71 Py_hash_t hash = (Py_hash_t)key >> 3;
72@@ -743,22 +742,24 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
73
74 /* Returns -1 on failure, 0 on success. */
75 static int
76-_PyMemoTable_ResizeTable(PyMemoTable *self, Py_ssize_t min_size)
77+_PyMemoTable_ResizeTable(PyMemoTable *self, size_t min_size)
78 {
79 PyMemoEntry *oldtable = NULL;
80 PyMemoEntry *oldentry, *newentry;
81- Py_ssize_t new_size = MT_MINSIZE;
82- Py_ssize_t to_process;
83+ size_t new_size = MT_MINSIZE;
84+ size_t to_process;
85
86 assert(min_size > 0);
87
88- /* Find the smallest valid table size >= min_size. */
89- while (new_size < min_size && new_size > 0)
90- new_size <<= 1;
91- if (new_size <= 0) {
92+ if (min_size > PY_SSIZE_T_MAX) {
93 PyErr_NoMemory();
94 return -1;
95 }
96+
97+ /* Find the smallest valid table size >= min_size. */
98+ while (new_size < min_size) {
99+ new_size <<= 1;
100+ }
101 /* new_size needs to be a power of two. */
102 assert((new_size & (new_size - 1)) == 0);
103
104@@ -808,6 +809,7 @@ static int
105 PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
106 {
107 PyMemoEntry *entry;
108+ size_t desired_size;
109
110 assert(key != NULL);
111
112@@ -831,10 +833,12 @@ PyMemoTable_Set(PyMemoTable *self, PyObject *key, Py_ssize_t value)
113 * Very large memo tables (over 50K items) use doubling instead.
114 * This may help applications with severe memory constraints.
115 */
116- if (!(self->mt_used * 3 >= (self->mt_mask + 1) * 2))
117+ if (SIZE_MAX / 3 >= self->mt_used && self->mt_used * 3 < self->mt_allocated * 2) {
118 return 0;
119- return _PyMemoTable_ResizeTable(self,
120- (self->mt_used > 50000 ? 2 : 4) * self->mt_used);
121+ }
122+ // self->mt_used is always < PY_SSIZE_T_MAX, so this can't overflow.
123+ desired_size = (self->mt_used > 50000 ? 2 : 4) * self->mt_used;
124+ return _PyMemoTable_ResizeTable(self, desired_size);
125 }
126
127 #undef MT_MINSIZE
128@@ -1273,9 +1277,9 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
129 /* Returns -1 (with an exception set) on failure, 0 on success. The memo array
130 will be modified in place. */
131 static int
132-_Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
133+_Unpickler_ResizeMemoList(UnpicklerObject *self, size_t new_size)
134 {
135- Py_ssize_t i;
136+ size_t i;
137
138 assert(new_size > self->memo_size);
139
140@@ -1292,9 +1296,9 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
141
142 /* Returns NULL if idx is out of bounds. */
143 static PyObject *
144-_Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
145+_Unpickler_MemoGet(UnpicklerObject *self, size_t idx)
146 {
147- if (idx < 0 || idx >= self->memo_size)
148+ if (idx >= self->memo_size)
149 return NULL;
150
151 return self->memo[idx];
152@@ -1303,7 +1307,7 @@ _Unpickler_MemoGet(UnpicklerObject *self, Py_ssize_t idx)
153 /* Returns -1 (with an exception set) on failure, 0 on success.
154 This takes its own reference to `value`. */
155 static int
156-_Unpickler_MemoPut(UnpicklerObject *self, Py_ssize_t idx, PyObject *value)
157+_Unpickler_MemoPut(UnpicklerObject *self, size_t idx, PyObject *value)
158 {
159 PyObject *old_item;
160
161@@ -4194,14 +4198,13 @@ static PyObject *
162 _pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self)
163 /*[clinic end generated code: output=bb83a919d29225ef input=b73043485ac30b36]*/
164 {
165- Py_ssize_t i;
166 PyMemoTable *memo;
167 PyObject *new_memo = PyDict_New();
168 if (new_memo == NULL)
169 return NULL;
170
171 memo = self->pickler->memo;
172- for (i = 0; i < memo->mt_allocated; ++i) {
173+ for (size_t i = 0; i < memo->mt_allocated; ++i) {
174 PyMemoEntry entry = memo->mt_table[i];
175 if (entry.me_key != NULL) {
176 int status;
177@@ -6620,7 +6623,7 @@ static PyObject *
178 _pickle_UnpicklerMemoProxy_copy_impl(UnpicklerMemoProxyObject *self)
179 /*[clinic end generated code: output=e12af7e9bc1e4c77 input=97769247ce032c1d]*/
180 {
181- Py_ssize_t i;
182+ size_t i;
183 PyObject *new_memo = PyDict_New();
184 if (new_memo == NULL)
185 return NULL;
186@@ -6771,8 +6774,7 @@ static int
187 Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
188 {
189 PyObject **new_memo;
190- Py_ssize_t new_memo_size = 0;
191- Py_ssize_t i;
192+ size_t new_memo_size = 0;
193
194 if (obj == NULL) {
195 PyErr_SetString(PyExc_TypeError,
196@@ -6789,7 +6791,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
197 if (new_memo == NULL)
198 return -1;
199
200- for (i = 0; i < new_memo_size; i++) {
201+ for (size_t i = 0; i < new_memo_size; i++) {
202 Py_XINCREF(unpickler->memo[i]);
203 new_memo[i] = unpickler->memo[i];
204 }
205@@ -6837,8 +6839,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
206
207 error:
208 if (new_memo_size) {
209- i = new_memo_size;
210- while (--i >= 0) {
211+ for (size_t i = new_memo_size - 1; i != SIZE_MAX; i--) {
212 Py_XDECREF(new_memo[i]);
213 }
214 PyMem_FREE(new_memo);
215--
2162.22.0.vfs.1.1.57.gbaf16c8
217