From 4b28bb6ced01fa4fb82482b6081fe41080d92bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Thu, 30 Oct 2025 12:05:07 +0100 Subject: [PATCH 1/3] Fix heap-after-use between 'PROXYSQL INTERNAL SESSION' and 'SHOW PROCESSLIST' Missing query cleanup in 'PROXYSQL INTERNAL SESSION' could lead to invalid memory accesses during 'SHOW PROCESSLIST' sessions scan. --- lib/Base_Session.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/Base_Session.cpp b/lib/Base_Session.cpp index 55b1250b3..e9f5bc112 100644 --- a/lib/Base_Session.cpp +++ b/lib/Base_Session.cpp @@ -304,6 +304,8 @@ void Base_Session::return_proxysql_internal(PtrSize_t* pkt) { bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF; SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot, false, deprecate_eof_active); delete resultset; + // NOTE: End request before freeing the packet; otherwise logging could use invalid memory + static_cast(this)->RequestEnd(NULL); l_free(pkt->size, pkt->ptr); return; } @@ -331,6 +333,8 @@ void Base_Session::return_proxysql_internal(PtrSize_t* pkt) { char txn_state = (nTxn ? 'T' : 'I'); SQLite3_to_Postgres(client_myds->PSarrayOUT, resultset, nullptr, 0, (const char*)pkt->ptr + 5, txn_state); delete resultset; + // NOTE: End request before freeing the packet; otherwise logging could use invalid memory + static_cast(this)->RequestEnd(NULL, false); l_free(pkt->size, pkt->ptr); return; } From 6ff850170b3ab67c18f51fbe29d565df1260d84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Thu, 30 Oct 2025 12:09:25 +0100 Subject: [PATCH 2/3] Add regression test triggering 'heap-after-use' for ASAN runs --- .../reg_test_proclist_use_after_free-t.cpp | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 test/tap/tests/reg_test_proclist_use_after_free-t.cpp diff --git a/test/tap/tests/reg_test_proclist_use_after_free-t.cpp b/test/tap/tests/reg_test_proclist_use_after_free-t.cpp new file mode 100644 index 000000000..ff675c0cd --- /dev/null +++ b/test/tap/tests/reg_test_proclist_use_after_free-t.cpp @@ -0,0 +1,87 @@ +/** + * @file reg_test_proclist_use_after_free-t.cpp + * @brief Created to find heap-after-use flow in 'SHOW PROCESSLIST'. + * @details Left as a regression test exercising the offending flow for ASAN runs. + */ + +#include +#include +#include +#include + +#include "mysql.h" + +#include "tap.h" +#include "command_line.h" +#include "utils.h" + +int main(int argc, char** argv) { + CommandLine cl; + + if (cl.getEnv()) { + diag("Failed to get the required environmental variables."); + return EXIT_FAILURE; + } + + MYSQL* proxy = mysql_init(NULL); + MYSQL* admin = mysql_init(NULL); + + if (!mysql_real_connect(proxy, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxy)); + return EXIT_FAILURE; + } + if (!mysql_real_connect(admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(admin)); + return EXIT_FAILURE; + } + + MYSQL_QUERY_T(proxy, + "CREATE TABLE IF NOT EXISTS test.auto_inc_multiplex " + "(c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, c2 VARCHAR(100), c3 VARCHAR(100))" + ); + MYSQL_QUERY_T(admin, "SET mysql-auto_increment_delay_multiplex=5"); + MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + + std::atomic p_done { false }; + + std::thread a_thread([&admin, &p_done] () -> int { + uint32_t timeout = 5; + uint32_t st_time = time(NULL); + uint32_t elapsed = 0; + + while (p_done == false && elapsed < timeout) { + MYSQL_QUERY_T(admin, "SHOW PROCESSLIST"); + mysql_free_result(mysql_store_result(admin)); + + elapsed = time(NULL) - st_time; + } + + return 0; + }); + + std::thread p_thread([&proxy, &p_done] () -> int { + for (size_t c = 0; c < 10; c++) { + MYSQL_QUERY_T(proxy, "INSERT INTO test.auto_inc_multiplex (c2, c3) VALUES ('foo','bar')"); + + for (size_t i = 0; i < 5; i++) { + MYSQL_QUERY_T(proxy, "DO 1"); + + MYSQL_QUERY_T(proxy, "PROXYSQL INTERNAL SESSION"); + mysql_free_result(mysql_store_result(proxy)); + } + } + + p_done = true; + return 0; + }); + + p_thread.join(); + a_thread.join(); + + MYSQL_QUERY_T(proxy, "DELETE FROM test.auto_inc_multiplex"); + + mysql_close(proxy); + mysql_close(admin); + + return exit_status(); +} From 7051857d9b4d66c438b38421a720167c909b0e94 Mon Sep 17 00:00:00 2001 From: Miro Stauder Date: Tue, 4 Nov 2025 18:42:51 +0000 Subject: [PATCH 3/3] add tap test to groups.json Signed-off-by: Miro Stauder --- test/tap/groups/groups.json | 1 + 1 file changed, 1 insertion(+) diff --git a/test/tap/groups/groups.json b/test/tap/groups/groups.json index c49515924..b76258319 100644 --- a/test/tap/groups/groups.json +++ b/test/tap/groups/groups.json @@ -53,6 +53,7 @@ "prepare_statement_err3024_async-t" : [ "default-g1","mysql-auto_increment_delay_multiplex=0-g1","mysql-multiplexing=false-g1","mysql-query_digests=0-g1","mysql-query_digests_keep_comment=1-g1" ], "prepare_statement_err3024_libmysql-t" : [ "default-g2","mysql-auto_increment_delay_multiplex=0-g2","mysql-multiplexing=false-g2","mysql-query_digests=0-g2","mysql-query_digests_keep_comment=1-g2" ], "prepare_statement_err3024-t" : [ "default-g2","mysql-auto_increment_delay_multiplex=0-g2","mysql-multiplexing=false-g2","mysql-query_digests=0-g2","mysql-query_digests_keep_comment=1-g2" ], + "reg_test_proclist_use_after_free-t" : [ "default-g2","mysql-auto_increment_delay_multiplex=0-g2","mysql-multiplexing=false-g2","mysql-query_digests=0-g2","mysql-query_digests_keep_comment=1-g2" ], "reg_test_1493-mixed_compression-t" : [ "default-g2","mysql-auto_increment_delay_multiplex=0-g2","mysql-multiplexing=false-g2","mysql-query_digests=0-g2","mysql-query_digests_keep_comment=1-g2" ], "reg_test_1574-mariadb_read_stmt_execute_response-t" : [ "default-g2","mysql-auto_increment_delay_multiplex=0-g2","mysql-multiplexing=false-g2","mysql-query_digests=0-g2","mysql-query_digests_keep_comment=1-g2" ], "reg_test_1574-stmt_metadata-t" : [ "default-g2","mysql-auto_increment_delay_multiplex=0-g2","mysql-multiplexing=false-g2","mysql-query_digests=0-g2","mysql-query_digests_keep_comment=1-g2" ],