Merge pull request #2222 from citusdata/fix_insert_select

Fix use-after-free that may occur for INSERT..SELECT in prepared statements

cr: @jasonmp85
pull/2224/head
Jason Petersen 2018-06-19 00:15:09 -06:00 committed by GitHub
commit bdc44f0d29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 1 deletions

View File

@ -101,6 +101,7 @@ ExecuteSelectIntoRelation(Oid targetRelationId, List *insertTargetList,
int partitionColumnIndex = -1; int partitionColumnIndex = -1;
CitusCopyDestReceiver *copyDest = NULL; CitusCopyDestReceiver *copyDest = NULL;
Query *queryCopy = NULL;
partitionMethod = PartitionMethod(targetRelationId); partitionMethod = PartitionMethod(targetRelationId);
if (partitionMethod == DISTRIBUTE_BY_NONE) if (partitionMethod == DISTRIBUTE_BY_NONE)
@ -135,7 +136,14 @@ ExecuteSelectIntoRelation(Oid targetRelationId, List *insertTargetList,
partitionColumnIndex, executorState, partitionColumnIndex, executorState,
stopOnFailure); stopOnFailure);
ExecuteQueryIntoDestReceiver(selectQuery, paramListInfo, (DestReceiver *) copyDest); /*
* Make a copy of the query, since ExecuteQueryIntoDestReceiver may scribble on it
* and we want it to be replanned every time if it is stored in a prepared
* statement.
*/
queryCopy = copyObject(selectQuery);
ExecuteQueryIntoDestReceiver(queryCopy, paramListInfo, (DestReceiver *) copyDest);
executorState->es_processed = copyDest->tuplesSent; executorState->es_processed = copyDest->tuplesSent;

View File

@ -2722,6 +2722,19 @@ SELECT * FROM coerce_agg;
2 | {2,2,2} 2 | {2,2,2}
(2 rows) (2 rows)
-- INSERT..SELECT + prepared statements + recursive planning
BEGIN;
PREPARE prepared_recursive_insert_select AS
INSERT INTO users_table
SELECT * FROM users_table
WHERE value_1 IN (SELECT value_2 FROM events_table OFFSET 0);
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
ROLLBACK;
-- wrap in a transaction to improve performance -- wrap in a transaction to improve performance
BEGIN; BEGIN;
DROP TABLE coerce_events; DROP TABLE coerce_events;

View File

@ -2090,6 +2090,20 @@ LIMIT 5;
SELECT * FROM coerce_agg; SELECT * FROM coerce_agg;
-- INSERT..SELECT + prepared statements + recursive planning
BEGIN;
PREPARE prepared_recursive_insert_select AS
INSERT INTO users_table
SELECT * FROM users_table
WHERE value_1 IN (SELECT value_2 FROM events_table OFFSET 0);
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
ROLLBACK;
-- wrap in a transaction to improve performance -- wrap in a transaction to improve performance
BEGIN; BEGIN;
DROP TABLE coerce_events; DROP TABLE coerce_events;