This is an automated email from the ASF dual-hosted git repository.

reshke pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 9252098e22c25af520784840dd632ca0f0d9f5cb
Author: Tom Lane <[email protected]>
AuthorDate: Tue Nov 1 12:48:01 2022 -0400

    pg_stat_statements: fetch stmt location/length before it disappears.
    
    When executing a utility statement, we must fetch everything
    we need out of the PlannedStmt data structure before calling
    standard_ProcessUtility.  In certain cases (possibly only ROLLBACK
    in extended query protocol), that data structure will get freed
    during command execution.  The situation is probably often harmless
    in production builds, but in debug builds we intentionally overwrite
    the freed memory with garbage, leading to picking up garbage values
    of statement location and length, typically causing an assertion
    failure later in pg_stat_statements.  In non-debug builds, if
    something did go wrong it would likely lead to storing garbage
    for the query string.
    
    Report and fix by zhaoqigui (with cosmetic adjustments by me).
    It's an old problem, so back-patch to all supported versions.
    
    Discussion: https://postgr.es/m/[email protected]
    Discussion: https://postgr.es/m/[email protected]
---
 contrib/pg_stat_statements/pg_stat_statements.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/contrib/pg_stat_statements/pg_stat_statements.c 
b/contrib/pg_stat_statements/pg_stat_statements.c
index b125bcca694..94c39f44f0c 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -1080,6 +1080,8 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char 
*queryString,
 {
        Node       *parsetree = pstmt->utilityStmt;
        uint64          saved_queryId = pstmt->queryId;
+       int                     saved_stmt_location = pstmt->stmt_location;
+       int                     saved_stmt_len = pstmt->stmt_len;
 
        /*
         * Force utility statements to get queryId zero.  We do this even in 
cases
@@ -1145,6 +1147,16 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char 
*queryString,
                }
                PG_END_TRY();
 
+               /*
+                * CAUTION: do not access the *pstmt data structure again below 
here.
+                * If it was a ROLLBACK or similar, that data structure may 
have been
+                * freed.  We must copy everything we still need into local 
variables,
+                * which we did above.
+                *
+                * For the same reason, we can't risk restoring pstmt->queryId 
to its
+                * former value, which'd otherwise be a good idea.
+                */
+
                INSTR_TIME_SET_CURRENT(duration);
                INSTR_TIME_SUBTRACT(duration, start);
 
@@ -1170,8 +1182,8 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char 
*queryString,
 
                pgss_store(queryString,
                                   saved_queryId,
-                                  pstmt->stmt_location,
-                                  pstmt->stmt_len,
+                                  saved_stmt_location,
+                                  saved_stmt_len,
                                   PGSS_EXEC,
                                   INSTR_TIME_GET_MILLISEC(duration),
                                   rows,


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to