bpo-32710: Fix _overlapped.Overlapped memory leaks (GH-11489) · python/cpython@059997d (original) (raw)
`@@ -561,6 +561,28 @@ Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
`
561
561
`return (PyObject *)self;
`
562
562
`}
`
563
563
``
``
564
+
``
565
`+
/* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release
`
``
566
`+
buffers while overlapped are still running, to prevent a crash. */
`
``
567
`+
static int
`
``
568
`+
Overlapped_clear(OverlappedObject *self)
`
``
569
`+
{
`
``
570
`+
switch (self->type) {
`
``
571
`+
case TYPE_READ:
`
``
572
`+
case TYPE_ACCEPT:
`
``
573
`+
Py_CLEAR(self->allocated_buffer);
`
``
574
`+
break;
`
``
575
`+
case TYPE_WRITE:
`
``
576
`+
case TYPE_READINTO:
`
``
577
`+
if (self->user_buffer.obj) {
`
``
578
`+
PyBuffer_Release(&self->user_buffer);
`
``
579
`+
}
`
``
580
`+
break;
`
``
581
`+
}
`
``
582
`+
self->type = TYPE_NOT_STARTED;
`
``
583
`+
return 0;
`
``
584
`+
}
`
``
585
+
564
586
`static void
`
565
587
`Overlapped_dealloc(OverlappedObject *self)
`
566
588
`{
`
`@@ -594,20 +616,11 @@ Overlapped_dealloc(OverlappedObject *self)
`
594
616
` }
`
595
617
` }
`
596
618
``
597
``
`-
if (self->overlapped.hEvent != NULL)
`
``
619
`+
if (self->overlapped.hEvent != NULL) {
`
598
620
`CloseHandle(self->overlapped.hEvent);
`
599
``
-
600
``
`-
switch (self->type) {
`
601
``
`-
case TYPE_READ:
`
602
``
`-
case TYPE_ACCEPT:
`
603
``
`-
Py_CLEAR(self->allocated_buffer);
`
604
``
`-
break;
`
605
``
`-
case TYPE_WRITE:
`
606
``
`-
case TYPE_READINTO:
`
607
``
`-
if (self->user_buffer.obj)
`
608
``
`-
PyBuffer_Release(&self->user_buffer);
`
609
``
`-
break;
`
610
621
` }
`
``
622
+
``
623
`+
Overlapped_clear(self);
`
611
624
`PyObject_Del(self);
`
612
625
`SetLastError(olderr);
`
613
626
`}
`
`@@ -723,8 +736,7 @@ do_ReadFile(OverlappedObject *self, HANDLE handle,
`
723
736
`case ERROR_IO_PENDING:
`
724
737
`Py_RETURN_NONE;
`
725
738
`default:
`
726
``
`-
PyBuffer_Release(&self->user_buffer);
`
727
``
`-
self->type = TYPE_NOT_STARTED;
`
``
739
`+
Overlapped_clear(self);
`
728
740
`return SetFromWindowsErr(err);
`
729
741
` }
`
730
742
`}
`
`@@ -827,7 +839,7 @@ do_WSARecv(OverlappedObject *self, HANDLE handle,
`
827
839
`case ERROR_IO_PENDING:
`
828
840
`Py_RETURN_NONE;
`
829
841
`default:
`
830
``
`-
self->type = TYPE_NOT_STARTED;
`
``
842
`+
Overlapped_clear(self);
`
831
843
`return SetFromWindowsErr(err);
`
832
844
` }
`
833
845
`}
`
`@@ -955,7 +967,7 @@ Overlapped_WriteFile(OverlappedObject *self, PyObject *args)
`
955
967
`case ERROR_IO_PENDING:
`
956
968
`Py_RETURN_NONE;
`
957
969
`default:
`
958
``
`-
self->type = TYPE_NOT_STARTED;
`
``
970
`+
Overlapped_clear(self);
`
959
971
`return SetFromWindowsErr(err);
`
960
972
` }
`
961
973
`}
`
`@@ -1012,8 +1024,7 @@ Overlapped_WSASend(OverlappedObject *self, PyObject *args)
`
1012
1024
`case ERROR_IO_PENDING:
`
1013
1025
`Py_RETURN_NONE;
`
1014
1026
`default:
`
1015
``
`-
PyBuffer_Release(&self->user_buffer);
`
1016
``
`-
self->type = TYPE_NOT_STARTED;
`
``
1027
`+
Overlapped_clear(self);
`
1017
1028
`return SetFromWindowsErr(err);
`
1018
1029
` }
`
1019
1030
`}
`
`@@ -1063,7 +1074,7 @@ Overlapped_AcceptEx(OverlappedObject *self, PyObject *args)
`
1063
1074
`case ERROR_IO_PENDING:
`
1064
1075
`Py_RETURN_NONE;
`
1065
1076
`default:
`
1066
``
`-
self->type = TYPE_NOT_STARTED;
`
``
1077
`+
Overlapped_clear(self);
`
1067
1078
`return SetFromWindowsErr(err);
`
1068
1079
` }
`
1069
1080
`}
`
`@@ -1155,7 +1166,7 @@ Overlapped_ConnectEx(OverlappedObject *self, PyObject *args)
`
1155
1166
`case ERROR_IO_PENDING:
`
1156
1167
`Py_RETURN_NONE;
`
1157
1168
`default:
`
1158
``
`-
self->type = TYPE_NOT_STARTED;
`
``
1169
`+
Overlapped_clear(self);
`
1159
1170
`return SetFromWindowsErr(err);
`
1160
1171
` }
`
1161
1172
`}
`
`@@ -1194,7 +1205,7 @@ Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args)
`
1194
1205
`case ERROR_IO_PENDING:
`
1195
1206
`Py_RETURN_NONE;
`
1196
1207
`default:
`
1197
``
`-
self->type = TYPE_NOT_STARTED;
`
``
1208
`+
Overlapped_clear(self);
`
1198
1209
`return SetFromWindowsErr(err);
`
1199
1210
` }
`
1200
1211
`}
`
`@@ -1249,7 +1260,7 @@ Overlapped_TransmitFile(OverlappedObject *self, PyObject *args)
`
1249
1260
`case ERROR_IO_PENDING:
`
1250
1261
`Py_RETURN_NONE;
`
1251
1262
`default:
`
1252
``
`-
self->type = TYPE_NOT_STARTED;
`
``
1263
`+
Overlapped_clear(self);
`
1253
1264
`return SetFromWindowsErr(err);
`
1254
1265
` }
`
1255
1266
`}
`
`@@ -1290,7 +1301,7 @@ Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args)
`
1290
1301
`case ERROR_IO_PENDING:
`
1291
1302
`Py_RETURN_FALSE;
`
1292
1303
`default:
`
1293
``
`-
self->type = TYPE_NOT_STARTED;
`
``
1304
`+
Overlapped_clear(self);
`
1294
1305
`return SetFromWindowsErr(err);
`
1295
1306
` }
`
1296
1307
`}
`
`@@ -1340,6 +1351,25 @@ Overlapped_getpending(OverlappedObject *self)
`
1340
1351
`self->type != TYPE_NOT_STARTED);
`
1341
1352
`}
`
1342
1353
``
``
1354
`+
static int
`
``
1355
`+
Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
`
``
1356
`+
{
`
``
1357
`+
switch (self->type) {
`
``
1358
`+
case TYPE_READ:
`
``
1359
`+
case TYPE_ACCEPT:
`
``
1360
`+
Py_VISIT(self->allocated_buffer);
`
``
1361
`+
break;
`
``
1362
`+
case TYPE_WRITE:
`
``
1363
`+
case TYPE_READINTO:
`
``
1364
`+
if (self->user_buffer.obj) {
`
``
1365
`+
Py_VISIT(&self->user_buffer.obj);
`
``
1366
`+
}
`
``
1367
`+
break;
`
``
1368
`+
}
`
``
1369
`+
return 0;
`
``
1370
`+
}
`
``
1371
+
``
1372
+
1343
1373
`static PyMethodDef Overlapped_methods[] = {
`
1344
1374
` {"getresult", (PyCFunction) Overlapped_getresult,
`
1345
1375
`METH_VARARGS, Overlapped_getresult_doc},
`
`@@ -1410,7 +1440,7 @@ PyTypeObject OverlappedType = {
`
1410
1440
`/* tp_as_buffer */ 0,
`
1411
1441
`/* tp_flags */ Py_TPFLAGS_DEFAULT,
`
1412
1442
`/* tp_doc */ "OVERLAPPED structure wrapper",
`
1413
``
`-
/* tp_traverse */ 0,
`
``
1443
`+
/* tp_traverse */ (traverseproc)Overlapped_traverse,
`
1414
1444
`/* tp_clear */ 0,
`
1415
1445
`/* tp_richcompare */ 0,
`
1416
1446
`/* tp_weaklistoffset */ 0,
`