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

Commit82ebf39

Browse files
committed
Save/restore SPI's global variables in SPI_connect() and SPI_finish().
This patch removes two sources of interference between nominallyindependent functions when one SPI-using function calls another,perhaps without knowing that it does so.Chapman Flack pointed out that xml.c's query_to_xml_internal() expectsSPI_tuptable and SPI_processed to stay valid across datatype outputfunction calls; but it's possible that such a call could involvere-entrant use of SPI. It seems likely that there are similar hazardselsewhere, if not in the core code then in third-party SPI users.Previously SPI_finish() reset SPI's API globals to zeroes/nulls, whichwould typically make for a crash in such a situation. Restoring themto the values they had at SPI_connect() seems like a considerably moreuseful behavior, and it still meets the design goal of not leaving anydangling pointers to tuple tables of the function being exited.Also, cause SPI_connect() to reset these variables to zeroes/nulls aftersaving them. This prevents interference in the opposite direction: it'spossible that a SPI-using function that's only ever been tested standalonecontains assumptions that these variables start out as zeroes. That wasthe case as long as you were the outermost SPI user, but not so much foran inner user. Now it's consistent.Report and fix suggestion by Chapman Flack, actual patch by me.Back-patch to all supported branches.Discussion:https://postgr.es/m/9fa25bef-2e4f-1c32-22a4-3ad0723c4a17@anastigmatix.net
1 parent2ef5c12 commit82ebf39

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

‎src/backend/executor/spi.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,16 @@
3636
#include"utils/typcache.h"
3737

3838

39+
/*
40+
* These global variables are part of the API for various SPI functions
41+
* (a horrible API choice, but it's too late now). To reduce the risk of
42+
* interference between different SPI callers, we save and restore them
43+
* when entering/exiting a SPI nesting level.
44+
*/
3945
uint64SPI_processed=0;
4046
OidSPI_lastoid=InvalidOid;
4147
SPITupleTable*SPI_tuptable=NULL;
42-
intSPI_result;
48+
intSPI_result=0;
4349

4450
static_SPI_connection*_SPI_stack=NULL;
4551
static_SPI_connection*_SPI_current=NULL;
@@ -132,6 +138,10 @@ SPI_connect(void)
132138
_SPI_current->procCxt=NULL;/* in case we fail to create 'em */
133139
_SPI_current->execCxt=NULL;
134140
_SPI_current->connectSubid=GetCurrentSubTransactionId();
141+
_SPI_current->outer_processed=SPI_processed;
142+
_SPI_current->outer_lastoid=SPI_lastoid;
143+
_SPI_current->outer_tuptable=SPI_tuptable;
144+
_SPI_current->outer_result=SPI_result;
135145

136146
/*
137147
* Create memory contexts for this procedure
@@ -150,6 +160,15 @@ SPI_connect(void)
150160
/* ... and switch to procedure's context */
151161
_SPI_current->savedcxt=MemoryContextSwitchTo(_SPI_current->procCxt);
152162

163+
/*
164+
* Reset API global variables so that current caller cannot accidentally
165+
* depend on state of an outer caller.
166+
*/
167+
SPI_processed=0;
168+
SPI_lastoid=InvalidOid;
169+
SPI_tuptable=NULL;
170+
SPI_result=0;
171+
153172
returnSPI_OK_CONNECT;
154173
}
155174

@@ -172,12 +191,13 @@ SPI_finish(void)
172191
_SPI_current->procCxt=NULL;
173192

174193
/*
175-
*Reset result variables, especially SPI_tuptable which is probably
194+
*Restore outer API variables, especially SPI_tuptable which is probably
176195
* pointing at a just-deleted tuptable
177196
*/
178-
SPI_processed=0;
179-
SPI_lastoid=InvalidOid;
180-
SPI_tuptable=NULL;
197+
SPI_processed=_SPI_current->outer_processed;
198+
SPI_lastoid=_SPI_current->outer_lastoid;
199+
SPI_tuptable=_SPI_current->outer_tuptable;
200+
SPI_result=_SPI_current->outer_result;
181201

182202
/*
183203
* After _SPI_begin_call _SPI_connected == _SPI_curid. Now we are closing
@@ -214,9 +234,11 @@ AtEOXact_SPI(bool isCommit)
214234
_SPI_current=_SPI_stack=NULL;
215235
_SPI_stack_depth=0;
216236
_SPI_connected=_SPI_curid=-1;
237+
/* Reset API global variables, too */
217238
SPI_processed=0;
218239
SPI_lastoid=InvalidOid;
219240
SPI_tuptable=NULL;
241+
SPI_result=0;
220242
}
221243

222244
/*
@@ -254,19 +276,21 @@ AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
254276
}
255277

256278
/*
257-
*Pop the stack entry andreset global variables. Unlike
279+
*Restore outer global variables andpop the stack entry. Unlike
258280
* SPI_finish(), we don't risk switching to memory contexts that might
259281
* be already gone.
260282
*/
283+
SPI_processed=connection->outer_processed;
284+
SPI_lastoid=connection->outer_lastoid;
285+
SPI_tuptable=connection->outer_tuptable;
286+
SPI_result=connection->outer_result;
287+
261288
_SPI_connected--;
262289
_SPI_curid=_SPI_connected;
263290
if (_SPI_connected==-1)
264291
_SPI_current=NULL;
265292
else
266293
_SPI_current=&(_SPI_stack[_SPI_connected]);
267-
SPI_processed=0;
268-
SPI_lastoid=InvalidOid;
269-
SPI_tuptable=NULL;
270294
}
271295

272296
if (found&&isCommit)

‎src/include/executor/spi_priv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ typedef struct
3434

3535
/* subtransaction in which current Executor call was started */
3636
SubTransactionIdexecSubid;
37+
38+
/* saved values of API global variables for previous nesting level */
39+
uint64outer_processed;
40+
Oidouter_lastoid;
41+
SPITupleTable*outer_tuptable;
42+
intouter_result;
3743
}_SPI_connection;
3844

3945
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp