Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1dd8e71

Browse files
committed
Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq.
1 parent a7db057 commit 1dd8e71

2 files changed

Lines changed: 24 additions & 50 deletions

File tree

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ Library
4242
- Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes.
4343
Patch written by William Orr.
4444

45+
- Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup
46+
and siftdown functions.
47+
4548
- Issue #23008: Fixed resolving attributes with boolean value is False in pydoc.
4649

4750
- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't

Modules/_heapqmodule.c

Lines changed: 21 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ annotated by François Pinard, and converted to C by Raymond Hettinger.
1111
static int
1212
_siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
1313
{
14-
PyObject *newitem, *parent, *olditem;
14+
PyObject *newitem, *parent;
15+
Py_ssize_t parentpos, size;
1516
int cmp;
16-
Py_ssize_t parentpos;
17-
Py_ssize_t size;
1817

1918
assert(PyList_Check(heap));
2019
size = PyList_GET_SIZE(heap);
@@ -23,60 +22,45 @@ _siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
2322
return -1;
2423
}
2524

26-
newitem = PyList_GET_ITEM(heap, pos);
27-
Py_INCREF(newitem);
2825
/* Follow the path to the root, moving parents down until finding
2926
a place newitem fits. */
30-
while (pos > startpos){
27+
newitem = PyList_GET_ITEM(heap, pos);
28+
while (pos > startpos) {
3129
parentpos = (pos - 1) >> 1;
3230
parent = PyList_GET_ITEM(heap, parentpos);
3331
cmp = PyObject_RichCompareBool(newitem, parent, Py_LT);
34-
if (cmp == -1) {
35-
Py_DECREF(newitem);
32+
if (cmp == -1)
3633
return -1;
37-
}
3834
if (size != PyList_GET_SIZE(heap)) {
39-
Py_DECREF(newitem);
4035
PyErr_SetString(PyExc_RuntimeError,
4136
"list changed size during iteration");
4237
return -1;
4338
}
4439
if (cmp == 0)
4540
break;
46-
Py_INCREF(parent);
47-
olditem = PyList_GET_ITEM(heap, pos);
41+
parent = PyList_GET_ITEM(heap, parentpos);
42+
newitem = PyList_GET_ITEM(heap, pos);
43+
PyList_SET_ITEM(heap, parentpos, newitem);
4844
PyList_SET_ITEM(heap, pos, parent);
49-
Py_DECREF(olditem);
5045
pos = parentpos;
51-
if (size != PyList_GET_SIZE(heap)) {
52-
PyErr_SetString(PyExc_RuntimeError,
53-
"list changed size during iteration");
54-
return -1;
55-
}
5646
}
57-
Py_DECREF(PyList_GET_ITEM(heap, pos));
58-
PyList_SET_ITEM(heap, pos, newitem);
5947
return 0;
6048
}
6149

6250
static int
6351
_siftup(PyListObject *heap, Py_ssize_t pos)
6452
{
6553
Py_ssize_t startpos, endpos, childpos, rightpos, limit;
54+
PyObject *tmp1, *tmp2;
6655
int cmp;
67-
PyObject *newitem, *tmp, *olditem;
68-
Py_ssize_t size;
6956

7057
assert(PyList_Check(heap));
71-
size = PyList_GET_SIZE(heap);
72-
endpos = size;
58+
endpos = PyList_GET_SIZE(heap);
7359
startpos = pos;
7460
if (pos >= endpos) {
7561
PyErr_SetString(PyExc_IndexError, "index out of range");
7662
return -1;
7763
}
78-
newitem = PyList_GET_ITEM(heap, pos);
79-
Py_INCREF(newitem);
8064

8165
/* Bubble up the smaller child until hitting a leaf. */
8266
limit = endpos / 2; /* smallest pos that has no child */
@@ -89,37 +73,24 @@ _siftup(PyListObject *heap, Py_ssize_t pos)
8973
PyList_GET_ITEM(heap, childpos),
9074
PyList_GET_ITEM(heap, rightpos),
9175
Py_LT);
92-
if (cmp == -1) {
93-
Py_DECREF(newitem);
76+
if (cmp == -1)
9477
return -1;
95-
}
9678
if (cmp == 0)
9779
childpos = rightpos;
98-
}
99-
if (size != PyList_GET_SIZE(heap)) {
100-
Py_DECREF(newitem);
101-
PyErr_SetString(PyExc_RuntimeError,
102-
"list changed size during iteration");
103-
return -1;
80+
if (endpos != PyList_GET_SIZE(heap)) {
81+
PyErr_SetString(PyExc_RuntimeError,
82+
"list changed size during iteration");
83+
return -1;
84+
}
10485
}
10586
/* Move the smaller child up. */
106-
tmp = PyList_GET_ITEM(heap, childpos);
107-
Py_INCREF(tmp);
108-
olditem = PyList_GET_ITEM(heap, pos);
109-
PyList_SET_ITEM(heap, pos, tmp);
110-
Py_DECREF(olditem);
87+
tmp1 = PyList_GET_ITEM(heap, childpos);
88+
tmp2 = PyList_GET_ITEM(heap, pos);
89+
PyList_SET_ITEM(heap, childpos, tmp2);
90+
PyList_SET_ITEM(heap, pos, tmp1);
11191
pos = childpos;
112-
if (size != PyList_GET_SIZE(heap)) {
113-
PyErr_SetString(PyExc_RuntimeError,
114-
"list changed size during iteration");
115-
return -1;
116-
}
11792
}
118-
119-
/* The leaf at pos is empty now. Put newitem there, and bubble
120-
it up to its final resting place (by sifting its parents down). */
121-
Py_DECREF(PyList_GET_ITEM(heap, pos));
122-
PyList_SET_ITEM(heap, pos, newitem);
93+
/* Bubble it up to its final resting place (by sifting its parents down). */
12394
return _siftdown(heap, startpos, pos);
12495
}
12596

0 commit comments

Comments
 (0)