Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit500d497

Browse files
committed
Repair double-free in SP-GIST rescan (bug #15378)
spgrescan would first reset traversalCxt, and then traverse apotentially non-empty stack containing pointers to traversalValueswhich had been allocated in those contexts, freeing them a secondtime. This bug originates in commitccd6eb4 where traversalValue wasintroduced.Repair by traversing the stack before the context reset; this isn'tideal, since it means doing retail pfree in a context that's about tobe reset, but the freeing of a stack entry is also done in otherplaces in the code during the scan so it's not worth trying torefactor it further. Regression test added.Backpatch to 9.6 where the problem was introduced.Per bug #15378; analysis and patch by me, originally from a report onIRC by user velix; see also PostGIS ticket #4174; review by AlexanderKorotkov.Discussion:https://postgr.es/m/153663176628.23136.11901365223750051490@wrigleys.postgresql.org
1 parent4fa3741 commit500d497

File tree

3 files changed

+40
-3
lines changed

3 files changed

+40
-3
lines changed

‎src/backend/access/spgist/spgscan.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ resetSpGistScanOpaque(SpGistScanOpaque so)
7474

7575
freeScanStack(so);
7676

77+
/*
78+
* clear traversal context before proceeding to the next scan; this must
79+
* not happen before the freeScanStack above, else we get double-free
80+
* crashes.
81+
*/
82+
MemoryContextReset(so->traversalCxt);
83+
7784
if (so->searchNulls)
7885
{
7986
/* Stack a work item to scan the null index entries */
@@ -212,9 +219,6 @@ spgrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
212219
{
213220
SpGistScanOpaqueso= (SpGistScanOpaque)scan->opaque;
214221

215-
/* clear traversal context before proceeding to the next scan */
216-
MemoryContextReset(so->traversalCxt);
217-
218222
/* copy scankeys into local storage */
219223
if (scankey&&scan->numberOfKeys>0)
220224
{

‎src/test/regress/expected/spgist.out

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@ delete from spgist_point_tbl where id % 2 = 1;
2323
-- would exercise it)
2424
delete from spgist_point_tbl where id < 10000;
2525
vacuum spgist_point_tbl;
26+
-- Test rescan paths (cf. bug #15378)
27+
-- use box and && rather than point, so that rescan happens when the
28+
-- traverse stack is non-empty
29+
create table spgist_box_tbl(id serial, b box);
30+
insert into spgist_box_tbl(b)
31+
select box(point(i,j),point(i+s,j+s))
32+
from generate_series(1,100,5) i,
33+
generate_series(1,100,5) j,
34+
generate_series(1,10) s;
35+
create index spgist_box_idx on spgist_box_tbl using spgist (b);
36+
select count(*)
37+
from (values (point(5,5)),(point(8,8)),(point(12,12))) v(p)
38+
where exists(select * from spgist_box_tbl b where b.b && box(v.p,v.p));
39+
count
40+
-------
41+
3
42+
(1 row)
43+
2644
-- The point opclass's choose method only uses the spgMatchNode action,
2745
-- so the other actions are not tested by the above. Create an index using
2846
-- text opclass, which uses the others actions.

‎src/test/regress/sql/spgist.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ delete from spgist_point_tbl where id < 10000;
3030

3131
vacuum spgist_point_tbl;
3232

33+
-- Test rescan paths (cf. bug #15378)
34+
-- use box and && rather than point, so that rescan happens when the
35+
-- traverse stack is non-empty
36+
37+
createtablespgist_box_tbl(idserial, bbox);
38+
insert into spgist_box_tbl(b)
39+
selectbox(point(i,j),point(i+s,j+s))
40+
from generate_series(1,100,5) i,
41+
generate_series(1,100,5) j,
42+
generate_series(1,10) s;
43+
createindexspgist_box_idxon spgist_box_tbl using spgist (b);
44+
45+
selectcount(*)
46+
from (values (point(5,5)),(point(8,8)),(point(12,12))) v(p)
47+
where exists(select*from spgist_box_tbl bwhereb.b &&box(v.p,v.p));
3348

3449
-- The point opclass's choose method only uses the spgMatchNode action,
3550
-- so the other actions are not tested by the above. Create an index using

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp