From fe52ab398956964b1c7e1e2739891b2ea82d30df Mon Sep 17 00:00:00 2001 From: Alexander van Gessel Date: Thu, 26 Jun 2014 18:14:51 +0200 Subject: [PATCH 1/2] Fix a memory leak in forum_user_handler --- src/server/forum_user_handler.cpp | 19 ++++++++++++++----- src/server/forum_user_handler.hpp | 5 ++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/server/forum_user_handler.cpp b/src/server/forum_user_handler.cpp index 5f9485032810..b48494e06ee2 100644 --- a/src/server/forum_user_handler.cpp +++ b/src/server/forum_user_handler.cpp @@ -115,7 +115,8 @@ bool fuh::user_exists(const std::string& name) { // Make a test query for this username try { - return mysql_fetch_row(db_query("SELECT username FROM " + db_users_table_ + " WHERE UPPER(username)=UPPER('" + name + "')")); + mysql_result res = db_query("SELECT username FROM " + db_users_table_ + " WHERE UPPER(username)=UPPER('" + name + "')"); + return mysql_fetch_row(res.get()); } catch (error& e) { ERR_UH << "Could not execute test query for user '" << name << "' :" << e.message << std::endl; // If the database is down just let all usernames log in @@ -248,7 +249,13 @@ void fuh::set_lastlogin(const std::string& user, const time_t& lastlogin) { } } -MYSQL_RES* fuh::db_query(const std::string& sql) { +struct result_deleter { + void operator()(MYSQL_RES *result) { + mysql_free_result(result); + } +}; + +fuh::mysql_result fuh::db_query(const std::string& sql) { if(mysql_query(conn, sql.c_str())) { WRN_UH << "not connected to database, reconnecting..." << std::endl; //Try to reconnect and execute query again @@ -258,11 +265,12 @@ MYSQL_RES* fuh::db_query(const std::string& sql) { throw error("Error querying database."); } } - return mysql_store_result(conn); + return mysql_result(mysql_store_result(conn), result_deleter()); } std::string fuh::db_query_to_string(const std::string& sql) { - return std::string(mysql_fetch_row(db_query(sql))[0]); + mysql_result res = db_query(sql); + return std::string(mysql_fetch_row(res.get())[0]); } @@ -292,7 +300,8 @@ bool fuh::extra_row_exists(const std::string& name) { // Make a test query for this username try { - return mysql_fetch_row(db_query("SELECT username FROM " + db_extra_table_ + " WHERE UPPER(username)=UPPER('" + name + "')")); + mysql_result res = db_query("SELECT username FROM " + db_extra_table_ + " WHERE UPPER(username)=UPPER('" + name + "')"); + return mysql_fetch_row(res.get()); } catch (error& e) { ERR_UH << "Could not execute test query for user '" << name << "' :" << e.message << std::endl; return false; diff --git a/src/server/forum_user_handler.hpp b/src/server/forum_user_handler.hpp index 0848fe174c4c..fe65af827fa2 100644 --- a/src/server/forum_user_handler.hpp +++ b/src/server/forum_user_handler.hpp @@ -19,6 +19,7 @@ #include +#include #include // The [user_handler] section in the server configuration @@ -93,8 +94,10 @@ class fuh : public user_handler { std::string db_name_, db_host_, db_user_, db_password_, db_users_table_, db_extra_table_; + typedef boost::shared_ptr mysql_result; + // Throws user_handler::error - MYSQL_RES* db_query(const std::string& query); + mysql_result db_query(const std::string& query); // Throws user_handler::error via db_query() std::string db_query_to_string(const std::string& query); From 907d34820bc858bdc0daff8ed198e91b87c66dec Mon Sep 17 00:00:00 2001 From: Alexander van Gessel Date: Sat, 28 Jun 2014 17:20:37 +0200 Subject: [PATCH 2/2] Add a comment explaining the use of boost::shared_ptr --- src/server/forum_user_handler.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/server/forum_user_handler.hpp b/src/server/forum_user_handler.hpp index fe65af827fa2..e4758787835a 100644 --- a/src/server/forum_user_handler.hpp +++ b/src/server/forum_user_handler.hpp @@ -94,6 +94,9 @@ class fuh : public user_handler { std::string db_name_, db_host_, db_user_, db_password_, db_users_table_, db_extra_table_; + // std::unique_ptr would be better, as the object isn't actually shared + // boost::scoped_ptr cannot be returned, so we can't use that + // TODO C++11: switch to std::unique_ptr typedef boost::shared_ptr mysql_result; // Throws user_handler::error