pgpool2.git / summary / log / commit / refs
commit 45d17b1f1b60d3980b842f4da8d1a3d141db6561
Author: Tatsuo Ishii <ishii@postgresql.org>
Date: Fri Jul 13 08:36:00 2018 +0000
Fix accessing already freed data in extended query.
When previous_message was set and accessed later on, it looked into
already freed data. This is because read_kind_from_backend() set the
pointer to the previous message in session context, and then released
the memory at the end of the function. No report from fields so far. I
just found this while testing Pgpool-II.
To fix this, store the previous message in the session context, rather
than storing the pointer. Also have a flag in the session context to
indicate whether a previous message is actually stored or not.
All the API for previous message has not been changed.
src/context/pool_session_context.c | 13 +++++++++----
src/include/context/pool_session_context.h | 7 +++++--
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/context/pool_session_context.c b/src/context/pool_session_context.c
index 79384d3f3..06d946473 100644
--- a/src/context/pool_session_context.c
+++ b/src/context/pool_session_context.c
@@ -1356,7 +1356,7 @@ void pool_pending_message_reset_previous_message(void)
(errmsg("pool_pending_message_reset_previous_message: session context is not initialized")));
return;
}
- session_context->previous_message = NULL;
+ session_context->previous_message_exists = false;
}
/*
@@ -1370,11 +1370,13 @@ void pool_pending_message_set_previous_message(POOL_PENDING_MESSAGE *message)
(errmsg("pool_pending_message_set_previous_message: session context is not initialized")));
return;
}
- session_context->previous_message = message;
+ session_context->previous_message_exists = true;
+ memcpy(&session_context->previous_message, message, sizeof(POOL_PENDING_MESSAGE));
}
/*
- * Get previous message.
+ * Get previous message. This actually returns the address of memory. Do not
+ * try to free using pool_pending_message_free_pending_message().
*/
POOL_PENDING_MESSAGE *pool_pending_message_get_previous_message(void)
{
@@ -1384,7 +1386,10 @@ POOL_PENDING_MESSAGE *pool_pending_message_get_previous_message(void)
(errmsg("pool_pending_message_get_previous_message: session context is not initialized")));
return NULL;
}
- return session_context->previous_message;
+ if (session_context->previous_message_exists == false)
+ return NULL;
+
+ return &session_context->previous_message;
}
/*
diff --git a/src/include/context/pool_session_context.h b/src/include/context/pool_session_context.h
index b0bec425c..af5ee4972 100644
--- a/src/include/context/pool_session_context.h
+++ b/src/include/context/pool_session_context.h
@@ -229,9 +229,12 @@ typedef struct {
List *pending_messages;
/*
- * The last pending message. Reset at Ready for query.
+ * The last pending message. Reset at Ready for query. Note that this is
+ * a shallow copy of pending message. Once the are is reset,
+ * previos_message_exists is set to false.
*/
- POOL_PENDING_MESSAGE *previous_message;
+ bool previous_message_exists;
+ POOL_PENDING_MESSAGE previous_message;
/* Protocol major version number */
int major;
[parent: 27a00560b098]