bpo-35008: Fix possible leaks in Element.setstate(). (GH-9924) · python/cpython@bcbefe2 (original) (raw)

`@@ -233,11 +233,29 @@ create_extra(ElementObject* self, PyObject* attrib)

`

233

233

`}

`

234

234

``

235

235

`LOCAL(void)

`

236

``

`-

dealloc_extra(ElementObject* self)

`

``

236

`+

dealloc_extra(ElementObjectExtra *extra)

`

237

237

`{

`

238

``

`-

ElementObjectExtra *myextra;

`

239

238

`Py_ssize_t i;

`

240

239

``

``

240

`+

if (!extra)

`

``

241

`+

return;

`

``

242

+

``

243

`+

Py_DECREF(extra->attrib);

`

``

244

+

``

245

`+

for (i = 0; i < extra->length; i++)

`

``

246

`+

Py_DECREF(extra->children[i]);

`

``

247

+

``

248

`+

if (extra->children != extra->_children)

`

``

249

`+

PyObject_Free(extra->children);

`

``

250

+

``

251

`+

PyObject_Free(extra);

`

``

252

`+

}

`

``

253

+

``

254

`+

LOCAL(void)

`

``

255

`+

clear_extra(ElementObject* self)

`

``

256

`+

{

`

``

257

`+

ElementObjectExtra *myextra;

`

``

258

+

241

259

`if (!self->extra)

`

242

260

`return;

`

243

261

``

`@@ -246,15 +264,7 @@ dealloc_extra(ElementObject* self)

`

246

264

`myextra = self->extra;

`

247

265

`self->extra = NULL;

`

248

266

``

249

``

`-

Py_DECREF(myextra->attrib);

`

250

``

-

251

``

`-

for (i = 0; i < myextra->length; i++)

`

252

``

`-

Py_DECREF(myextra->children[i]);

`

253

``

-

254

``

`-

if (myextra->children != myextra->_children)

`

255

``

`-

PyObject_Free(myextra->children);

`

256

``

-

257

``

`-

PyObject_Free(myextra);

`

``

267

`+

dealloc_extra(myextra);

`

258

268

`}

`

259

269

``

260

270

`/* Convenience internal function to create new Element objects with the given

`

`@@ -420,6 +430,7 @@ element_resize(ElementObject* self, Py_ssize_t extra)

`

420

430

`Py_ssize_t size;

`

421

431

`PyObject* *children;

`

422

432

``

``

433

`+

assert(extra >= 0);

`

423

434

`/* make sure self->children can hold the given number of extra

`

424

435

` elements. set an exception and return -1 if allocation failed */

`

425

436

``

`@@ -624,7 +635,7 @@ element_gc_clear(ElementObject *self)

`

624

635

`/* After dropping all references from extra, it's no longer valid anyway,

`

625

636

` * so fully deallocate it.

`

626

637

` */

`

627

``

`-

dealloc_extra(self);

`

``

638

`+

clear_extra(self);

`

628

639

`return 0;

`

629

640

`}

`

630

641

``

`@@ -676,7 +687,7 @@ static PyObject *

`

676

687

`_elementtree_Element_clear_impl(ElementObject *self)

`

677

688

`/[clinic end generated code: output=8bcd7a51f94cfff6 input=3c719ff94bf45dd6]/

`

678

689

`{

`

679

``

`-

dealloc_extra(self);

`

``

690

`+

clear_extra(self);

`

680

691

``

681

692

`Py_INCREF(Py_None);

`

682

693

`_set_joined_ptr(&self->text, Py_None);

`

`@@ -710,6 +721,7 @@ _elementtree_Element___copy___impl(ElementObject *self)

`

710

721

`Py_INCREF(JOIN_OBJ(self->tail));

`

711

722

`_set_joined_ptr(&element->tail, self->tail);

`

712

723

``

``

724

`+

assert(!element->extra || !element->extra->length);

`

713

725

`if (self->extra) {

`

714

726

`if (element_resize(element, self->extra->length) < 0) {

`

715

727

`Py_DECREF(element);

`

`@@ -721,6 +733,7 @@ _elementtree_Element___copy___impl(ElementObject *self)

`

721

733

`element->extra->children[i] = self->extra->children[i];

`

722

734

` }

`

723

735

``

``

736

`+

assert(!element->extra->length);

`

724

737

`element->extra->length = self->extra->length;

`

725

738

` }

`

726

739

``

`@@ -783,6 +796,7 @@ elementtree_Element___deepcopy_(ElementObject *self, PyObject *memo)

`

783

796

` goto error;

`

784

797

`_set_joined_ptr(&element->tail, JOIN_SET(tail, JOIN_GET(self->tail)));

`

785

798

``

``

799

`+

assert(!element->extra || !element->extra->length);

`

786

800

`if (self->extra) {

`

787

801

`if (element_resize(element, self->extra->length) < 0)

`

788

802

` goto error;

`

`@@ -796,6 +810,7 @@ elementtree_Element___deepcopy_(ElementObject *self, PyObject *memo)

`

796

810

`element->extra->children[i] = child;

`

797

811

` }

`

798

812

``

``

813

`+

assert(!element->extra->length);

`

799

814

`element->extra->length = self->extra->length;

`

800

815

` }

`

801

816

``

`@@ -956,6 +971,7 @@ element_setstate_from_attributes(ElementObject *self,

`

956

971

`PyObject *children)

`

957

972

`{

`

958

973

`Py_ssize_t i, nchildren;

`

``

974

`+

ElementObjectExtra *oldextra = NULL;

`

959

975

``

960

976

`if (!tag) {

`

961

977

`PyErr_SetString(PyExc_TypeError, "tag may not be NULL");

`

`@@ -974,41 +990,58 @@ element_setstate_from_attributes(ElementObject *self,

`

974

990

`_set_joined_ptr(&self->tail, tail);

`

975

991

``

976

992

`/* Handle ATTRIB and CHILDREN. */

`

977

``

`-

if (!children && !attrib)

`

``

993

`+

if (!children && !attrib) {

`

978

994

`Py_RETURN_NONE;

`

``

995

`+

}

`

979

996

``

980

997

`/* Compute 'nchildren'. */

`

981

998

`if (children) {

`

982

999

`if (!PyList_Check(children)) {

`

983

1000

`PyErr_SetString(PyExc_TypeError, "'_children' is not a list");

`

984

1001

`return NULL;

`

985

1002

` }

`

986

``

`-

nchildren = PyList_Size(children);

`

987

``

`-

}

`

988

``

`-

else {

`

989

``

`-

nchildren = 0;

`

990

``

`-

}

`

``

1003

`+

nchildren = PyList_GET_SIZE(children);

`

991

1004

``

992

``

`-

/* Allocate 'extra'. */

`

993

``

`-

if (element_resize(self, nchildren)) {

`

994

``

`-

return NULL;

`

995

``

`-

}

`

996

``

`-

assert(self->extra && self->extra->allocated >= nchildren);

`

``

1005

`+

/* (Re-)allocate 'extra'.

`

``

1006

`+

Avoid DECREFs calling into this code again (cycles, etc.)

`

``

1007

`+

*/

`

``

1008

`+

oldextra = self->extra;

`

``

1009

`+

self->extra = NULL;

`

``

1010

`+

if (element_resize(self, nchildren)) {

`

``

1011

`+

assert(!self->extra || !self->extra->length);

`

``

1012

`+

clear_extra(self);

`

``

1013

`+

self->extra = oldextra;

`

``

1014

`+

return NULL;

`

``

1015

`+

}

`

``

1016

`+

assert(self->extra);

`

``

1017

`+

assert(self->extra->allocated >= nchildren);

`

``

1018

`+

if (oldextra) {

`

``

1019

`+

assert(self->extra->attrib == Py_None);

`

``

1020

`+

self->extra->attrib = oldextra->attrib;

`

``

1021

`+

oldextra->attrib = Py_None;

`

``

1022

`+

}

`

997

1023

``

998

``

`-

/* Copy children */

`

999

``

`-

for (i = 0; i < nchildren; i++) {

`

1000

``

`-

self->extra->children[i] = PyList_GET_ITEM(children, i);

`

1001

``

`-

Py_INCREF(self->extra->children[i]);

`

1002

``

`-

}

`

``

1024

`+

/* Copy children */

`

``

1025

`+

for (i = 0; i < nchildren; i++) {

`

``

1026

`+

self->extra->children[i] = PyList_GET_ITEM(children, i);

`

``

1027

`+

Py_INCREF(self->extra->children[i]);

`

``

1028

`+

}

`

1003

1029

``

1004

``

`-

self->extra->length = nchildren;

`

1005

``

`-

self->extra->allocated = nchildren;

`

``

1030

`+

assert(!self->extra->length);

`

``

1031

`+

self->extra->length = nchildren;

`

``

1032

`+

}

`

``

1033

`+

else {

`

``

1034

`+

if (element_resize(self, 0)) {

`

``

1035

`+

return NULL;

`

``

1036

`+

}

`

``

1037

`+

}

`

1006

1038

``

1007

1039

`/* Stash attrib. */

`

1008

1040

`if (attrib) {

`

1009

1041

`Py_INCREF(attrib);

`

1010

1042

`Py_XSETREF(self->extra->attrib, attrib);

`

1011

1043

` }

`

``

1044

`+

dealloc_extra(oldextra);

`

1012

1045

``

1013

1046

`Py_RETURN_NONE;

`

1014

1047

`}

`