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,

`