Skip to content

Commit 962051e

Browse files
bpo-34395: Fix memory leaks caused by incautious usage of PyMem_Resize(). (GH-8756)
(cherry picked from commit 67b9cc8) Co-authored-by: Sergey Fedoseev <[email protected]>
1 parent 64336dc commit 962051e

File tree

2 files changed

+22
-42
lines changed

2 files changed

+22
-42
lines changed

Modules/_csv.c

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -554,25 +554,17 @@ parse_save_field(ReaderObj *self)
554554
static int
555555
parse_grow_buff(ReaderObj *self)
556556
{
557-
if (self->field_size == 0) {
558-
self->field_size = 4096;
559-
if (self->field != NULL)
560-
PyMem_Free(self->field);
561-
self->field = PyMem_New(Py_UCS4, self->field_size);
562-
}
563-
else {
564-
Py_UCS4 *field = self->field;
565-
if (self->field_size > PY_SSIZE_T_MAX / 2) {
566-
PyErr_NoMemory();
567-
return 0;
568-
}
569-
self->field_size *= 2;
570-
self->field = PyMem_Resize(field, Py_UCS4, self->field_size);
571-
}
572-
if (self->field == NULL) {
557+
assert((size_t)self->field_size <= PY_SSIZE_T_MAX / sizeof(Py_UCS4));
558+
559+
Py_ssize_t field_size_new = self->field_size ? 2 * self->field_size : 4096;
560+
Py_UCS4 *field_new = self->field;
561+
PyMem_Resize(field_new, Py_UCS4, field_size_new);
562+
if (field_new == NULL) {
573563
PyErr_NoMemory();
574564
return 0;
575565
}
566+
self->field = field_new;
567+
self->field_size = field_size_new;
576568
return 1;
577569
}
578570

@@ -1088,31 +1080,18 @@ join_append_data(WriterObj *self, unsigned int field_kind, void *field_data,
10881080
static int
10891081
join_check_rec_size(WriterObj *self, Py_ssize_t rec_len)
10901082
{
1091-
1092-
if (rec_len < 0 || rec_len > PY_SSIZE_T_MAX - MEM_INCR) {
1093-
PyErr_NoMemory();
1094-
return 0;
1095-
}
1083+
assert(rec_len >= 0);
10961084

10971085
if (rec_len > self->rec_size) {
1098-
if (self->rec_size == 0) {
1099-
self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR;
1100-
if (self->rec != NULL)
1101-
PyMem_Free(self->rec);
1102-
self->rec = PyMem_New(Py_UCS4, self->rec_size);
1103-
}
1104-
else {
1105-
Py_UCS4* old_rec = self->rec;
1106-
1107-
self->rec_size = (rec_len / MEM_INCR + 1) * MEM_INCR;
1108-
self->rec = PyMem_Resize(old_rec, Py_UCS4, self->rec_size);
1109-
if (self->rec == NULL)
1110-
PyMem_Free(old_rec);
1111-
}
1112-
if (self->rec == NULL) {
1086+
size_t rec_size_new = (size_t)(rec_len / MEM_INCR + 1) * MEM_INCR;
1087+
Py_UCS4 *rec_new = self->rec;
1088+
PyMem_Resize(rec_new, Py_UCS4, rec_size_new);
1089+
if (rec_new == NULL) {
11131090
PyErr_NoMemory();
11141091
return 0;
11151092
}
1093+
self->rec = rec_new;
1094+
self->rec_size = (Py_ssize_t)rec_size_new;
11161095
}
11171096
return 1;
11181097
}

Modules/_pickle.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,11 +1380,13 @@ _Unpickler_ResizeMemoList(UnpicklerObject *self, Py_ssize_t new_size)
13801380

13811381
assert(new_size > self->memo_size);
13821382

1383-
PyMem_RESIZE(self->memo, PyObject *, new_size);
1384-
if (self->memo == NULL) {
1383+
PyObject **memo_new = self->memo;
1384+
PyMem_RESIZE(memo_new, PyObject *, new_size);
1385+
if (memo_new == NULL) {
13851386
PyErr_NoMemory();
13861387
return -1;
13871388
}
1389+
self->memo = memo_new;
13881390
for (i = self->memo_size; i < new_size; i++)
13891391
self->memo[i] = NULL;
13901392
self->memo_size = new_size;
@@ -6297,11 +6299,10 @@ load_mark(UnpicklerObject *self)
62976299
return -1;
62986300
}
62996301

6300-
if (self->marks == NULL)
6301-
self->marks = PyMem_NEW(Py_ssize_t, alloc);
6302-
else
6303-
PyMem_RESIZE(self->marks, Py_ssize_t, alloc);
6302+
Py_ssize_t *marks_old = self->marks;
6303+
PyMem_RESIZE(self->marks, Py_ssize_t, alloc);
63046304
if (self->marks == NULL) {
6305+
PyMem_FREE(marks_old);
63056306
self->marks_size = 0;
63066307
PyErr_NoMemory();
63076308
return -1;

0 commit comments

Comments
 (0)