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]