diff --git a/SOURCES/0001-Memory-leak-in-SQLPrepare-with-queries-that-use-para.patch b/SOURCES/0001-Memory-leak-in-SQLPrepare-with-queries-that-use-para.patch new file mode 100644 index 0000000..742ad19 --- /dev/null +++ b/SOURCES/0001-Memory-leak-in-SQLPrepare-with-queries-that-use-para.patch @@ -0,0 +1,148 @@ +From 4cf222c082950ff6a713792f68e2a2882135199e Mon Sep 17 00:00:00 2001 +From: Bogdan Degtyariov +Date: Wed, 4 Sep 2013 16:46:27 +1000 +Subject: [PATCH] Memory leak in SQLPrepare with queries that use parameters + (Bug# 17400483/70113) - no test case + +--- + ChangeLog | 2 ++ + driver/catalog_no_i_s.c | 1 + + driver/my_prepared_stmt.c | 21 ++++++++++++++------- + driver/my_stmt.c | 35 ++++++++++++++++++++++------------- + 4 files changed, 39 insertions(+), 20 deletions(-) + +diff --git a/driver/catalog_no_i_s.c b/driver/catalog_no_i_s.c +index ac54d3e..be4d616 100644 +--- a/driver/catalog_no_i_s.c ++++ b/driver/catalog_no_i_s.c +@@ -2141,6 +2141,7 @@ mysql_tables(SQLHSTMT hstmt, + if (!row_count) + { + mysql_free_result(stmt->result); ++ stmt->result= NULL; + goto empty_set; + } + +diff --git a/driver/my_prepared_stmt.c b/driver/my_prepared_stmt.c +index 71a5648..126d892 100644 +--- a/driver/my_prepared_stmt.c ++++ b/driver/my_prepared_stmt.c +@@ -1,5 +1,5 @@ + /* +- Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ Copyright (c) 2012-2013, Oracle and/or its affiliates. All rights reserved. + + The MySQL Connector/ODBC is licensed under the terms of the GPLv2 + , like most +@@ -223,10 +223,17 @@ void free_result_bind(STMT *stmt) + { + if (stmt->result_bind != NULL) + { ++ int i, field_cnt= field_count(stmt); ++ + x_free(stmt->result_bind[0].is_null); + x_free(stmt->result_bind[0].length); + x_free(stmt->result_bind[0].error); +- x_free(stmt->result_bind[0].buffer); ++ ++ /* buffer was allocated for each column */ ++ for (i= 0; i < field_cnt; i++) ++ { ++ x_free(stmt->result_bind[i].buffer); ++ } + + x_free(stmt->result_bind); + stmt->result_bind= 0; +@@ -438,11 +445,11 @@ int ssps_bind_result(STMT *stmt) + IS_PS_OUT_PARAMS(stmt)); + + stmt->result_bind[i].buffer_type = p.type; +- stmt->result_bind[i].buffer = p.buffer; +- stmt->result_bind[i].buffer_length= (unsigned long)p.size; +- stmt->result_bind[i].length = &len[i]; +- stmt->result_bind[i].is_null = &is_null[i]; +- stmt->result_bind[i].error = &err[i]; ++ stmt->result_bind[i].buffer = p.buffer; ++ stmt->result_bind[i].buffer_length= (unsigned long)p.size; ++ stmt->result_bind[i].length = &len[i]; ++ stmt->result_bind[i].is_null = &is_null[i]; ++ stmt->result_bind[i].error = &err[i]; + stmt->result_bind[i].is_unsigned = (field->flags & UNSIGNED_FLAG)? 1: 0; + + stmt->array[i]= p.buffer; +diff --git a/driver/my_stmt.c b/driver/my_stmt.c +index 0dd059f..6e201d5 100644 +--- a/driver/my_stmt.c ++++ b/driver/my_stmt.c +@@ -44,7 +44,16 @@ BOOL returned_result(STMT *stmt) + if (ssps_used(stmt)) + { + /* Basically at this point we are supposed to get result already */ +- return stmt->result ? TRUE : mysql_stmt_result_metadata(stmt->ssps) != NULL; ++ MYSQL_RES *temp_res= NULL; ++ ++ if ((stmt->result != NULL) || ++ (temp_res= mysql_stmt_result_metadata(stmt->ssps)) != NULL) ++ { ++ /* mysql_free_result checks for NULL, so we can always call it */ ++ mysql_free_result(temp_res); ++ return TRUE; ++ } ++ return FALSE; + } + else + { +@@ -55,24 +64,18 @@ BOOL returned_result(STMT *stmt) + + my_bool free_current_result(STMT *stmt) + { ++ my_bool res= 0; + if (returned_result(stmt)) + { + if (ssps_used(stmt)) +- +- { +- my_bool res= mysql_stmt_free_result(stmt->ssps); +- stmt->result= NULL; +- +- return res; +- } +- else + { +- mysql_free_result(stmt->result); +- stmt->result= NULL; +- return '\0'; ++ res= mysql_stmt_free_result(stmt->ssps); + } ++ /* We need to always free stmt->result because SSPS keep metadata there */ ++ mysql_free_result(stmt->result); ++ stmt->result= NULL; + } +- return '\0'; ++ return res; + } + + +@@ -98,6 +101,9 @@ MYSQL_RES * stmt_get_result(STMT *stmt, BOOL force_use) + we need to use/store each resultset of multiple resultsets */ + MYSQL_RES * get_result_metadata(STMT *stmt, BOOL force_use) + { ++ /* just a precaution, mysql_free_result checks for NULL anywat */ ++ mysql_free_result(stmt->result); ++ + if (ssps_used(stmt)) + { + stmt->result= mysql_stmt_result_metadata(stmt->ssps); +@@ -399,6 +405,9 @@ SQLRETURN prepare(STMT *stmt, char * query, SQLINTEGER query_length) + + stmt->param_count= mysql_stmt_param_count(stmt->ssps); + ++ /* make sure we free the result from the previous time */ ++ mysql_free_result(stmt->result); ++ + /* Getting result metadata */ + if ((stmt->result= mysql_stmt_result_metadata(stmt->ssps))) + { +-- +2.13.3 + diff --git a/SPECS/mysql-connector-odbc.spec b/SPECS/mysql-connector-odbc.spec index 4647e9e..bb202f6 100644 --- a/SPECS/mysql-connector-odbc.spec +++ b/SPECS/mysql-connector-odbc.spec @@ -1,7 +1,7 @@ Summary: ODBC driver for MySQL Name: mysql-connector-odbc Version: 5.2.5 -Release: 6%{?dist} +Release: 7%{?dist} Group: System Environment/Libraries URL: http://dev.mysql.com/downloads/connector/odbc/ # exceptions allow library to be linked with most open source SW, @@ -33,6 +33,7 @@ Patch8: mysql-connector-odbc-buffsize.patch Patch9: mysql-connector-odbc-cleartext.patch Patch10: mysql-connector-odbc-cond.patch Patch11: mysql-connector-odbc-5.2.5-aarch64.patch +Patch12: 0001-Memory-leak-in-SQLPrepare-with-queries-that-use-para.patch BuildRequires: mysql-devel unixODBC-devel BuildRequires: cmake @@ -57,6 +58,7 @@ tar xfz %{SOURCE1} %patch9 -p1 %patch10 -p1 %patch11 -p1 +%patch12 -p1 %build # mysql 5.5.10 has stopped #define'ing THREAD in its exports, and has @@ -103,6 +105,10 @@ rm -rf $RPM_BUILD_ROOT/usr/test %{_libdir}/lib*so %changelog +* Fri Oct 13 2017 Augusto Caringi - 5.2.5-7 +- Add patch to fix memory leak in SQLPrepare. + Resolves: #1425160 + * Fri Jan 24 2014 Daniel Mach - 5.2.5-6 - Mass rebuild 2014-01-24