diff options
Diffstat (limited to 'meta/recipes-devtools/python/python3/CVE-2018-20406.patch')
-rw-r--r-- | meta/recipes-devtools/python/python3/CVE-2018-20406.patch | 217 |
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 @@ | |||
1 | From 3c7fd2b2729e3ebcf7877e7a32b3bbabf907a38d Mon Sep 17 00:00:00 2001 | ||
2 | From: Victor Stinner <vstinner@redhat.com> | ||
3 | Date: Tue, 26 Feb 2019 01:42:39 +0100 | ||
4 | Subject: [PATCH] closes bpo-34656: Avoid relying on signed overflow in _pickle | ||
5 | memos. (GH-9261) (#11869) | ||
6 | |||
7 | (cherry picked from commit a4ae828ee416a66d8c7bf5ee71d653c2cc6a26dd) | ||
8 | |||
9 | CVE: CVE-2018-20406 | ||
10 | Upstream-Status: Backport | ||
11 | [https://github.com/python/cpython/commit/ef33dd6036aafbd3f06c1d56e2b1a81dae3da63c] | ||
12 | |||
13 | Signed-off-by: Dan Tran <dantran@microsoft.com> | ||
14 | --- | ||
15 | Modules/_pickle.c | 63 ++++++++++++++++++++++++----------------------- | ||
16 | 1 file changed, 32 insertions(+), 31 deletions(-) | ||
17 | |||
18 | diff --git a/Modules/_pickle.c b/Modules/_pickle.c | ||
19 | index 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 | -- | ||
216 | 2.22.0.vfs.1.1.57.gbaf16c8 | ||
217 | |||