|
|
98da24 |
From 4cf222c082950ff6a713792f68e2a2882135199e Mon Sep 17 00:00:00 2001
|
|
|
98da24 |
From: Bogdan Degtyariov <bogdan.degtyariov@oracle.com>
|
|
|
98da24 |
Date: Wed, 4 Sep 2013 16:46:27 +1000
|
|
|
98da24 |
Subject: [PATCH] Memory leak in SQLPrepare with queries that use parameters
|
|
|
98da24 |
(Bug# 17400483/70113) - no test case
|
|
|
98da24 |
|
|
|
98da24 |
---
|
|
|
98da24 |
ChangeLog | 2 ++
|
|
|
98da24 |
driver/catalog_no_i_s.c | 1 +
|
|
|
98da24 |
driver/my_prepared_stmt.c | 21 ++++++++++++++-------
|
|
|
98da24 |
driver/my_stmt.c | 35 ++++++++++++++++++++++-------------
|
|
|
98da24 |
4 files changed, 39 insertions(+), 20 deletions(-)
|
|
|
98da24 |
|
|
|
98da24 |
diff --git a/driver/catalog_no_i_s.c b/driver/catalog_no_i_s.c
|
|
|
98da24 |
index ac54d3e..be4d616 100644
|
|
|
98da24 |
--- a/driver/catalog_no_i_s.c
|
|
|
98da24 |
+++ b/driver/catalog_no_i_s.c
|
|
|
98da24 |
@@ -2141,6 +2141,7 @@ mysql_tables(SQLHSTMT hstmt,
|
|
|
98da24 |
if (!row_count)
|
|
|
98da24 |
{
|
|
|
98da24 |
mysql_free_result(stmt->result);
|
|
|
98da24 |
+ stmt->result= NULL;
|
|
|
98da24 |
goto empty_set;
|
|
|
98da24 |
}
|
|
|
98da24 |
|
|
|
98da24 |
diff --git a/driver/my_prepared_stmt.c b/driver/my_prepared_stmt.c
|
|
|
98da24 |
index 71a5648..126d892 100644
|
|
|
98da24 |
--- a/driver/my_prepared_stmt.c
|
|
|
98da24 |
+++ b/driver/my_prepared_stmt.c
|
|
|
98da24 |
@@ -1,5 +1,5 @@
|
|
|
98da24 |
/*
|
|
|
98da24 |
- Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
|
|
98da24 |
+ Copyright (c) 2012-2013, Oracle and/or its affiliates. All rights reserved.
|
|
|
98da24 |
|
|
|
98da24 |
The MySQL Connector/ODBC is licensed under the terms of the GPLv2
|
|
|
98da24 |
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
|
|
|
98da24 |
@@ -223,10 +223,17 @@ void free_result_bind(STMT *stmt)
|
|
|
98da24 |
{
|
|
|
98da24 |
if (stmt->result_bind != NULL)
|
|
|
98da24 |
{
|
|
|
98da24 |
+ int i, field_cnt= field_count(stmt);
|
|
|
98da24 |
+
|
|
|
98da24 |
x_free(stmt->result_bind[0].is_null);
|
|
|
98da24 |
x_free(stmt->result_bind[0].length);
|
|
|
98da24 |
x_free(stmt->result_bind[0].error);
|
|
|
98da24 |
- x_free(stmt->result_bind[0].buffer);
|
|
|
98da24 |
+
|
|
|
98da24 |
+ /* buffer was allocated for each column */
|
|
|
98da24 |
+ for (i= 0; i < field_cnt; i++)
|
|
|
98da24 |
+ {
|
|
|
98da24 |
+ x_free(stmt->result_bind[i].buffer);
|
|
|
98da24 |
+ }
|
|
|
98da24 |
|
|
|
98da24 |
x_free(stmt->result_bind);
|
|
|
98da24 |
stmt->result_bind= 0;
|
|
|
98da24 |
@@ -438,11 +445,11 @@ int ssps_bind_result(STMT *stmt)
|
|
|
98da24 |
IS_PS_OUT_PARAMS(stmt));
|
|
|
98da24 |
|
|
|
98da24 |
stmt->result_bind[i].buffer_type = p.type;
|
|
|
98da24 |
- stmt->result_bind[i].buffer = p.buffer;
|
|
|
98da24 |
- stmt->result_bind[i].buffer_length= (unsigned long)p.size;
|
|
|
98da24 |
- stmt->result_bind[i].length = &len[i];
|
|
|
98da24 |
- stmt->result_bind[i].is_null = &is_null[i];
|
|
|
98da24 |
- stmt->result_bind[i].error = &err[i];
|
|
|
98da24 |
+ stmt->result_bind[i].buffer = p.buffer;
|
|
|
98da24 |
+ stmt->result_bind[i].buffer_length= (unsigned long)p.size;
|
|
|
98da24 |
+ stmt->result_bind[i].length = &len[i];
|
|
|
98da24 |
+ stmt->result_bind[i].is_null = &is_null[i];
|
|
|
98da24 |
+ stmt->result_bind[i].error = &err[i];
|
|
|
98da24 |
stmt->result_bind[i].is_unsigned = (field->flags & UNSIGNED_FLAG)? 1: 0;
|
|
|
98da24 |
|
|
|
98da24 |
stmt->array[i]= p.buffer;
|
|
|
98da24 |
diff --git a/driver/my_stmt.c b/driver/my_stmt.c
|
|
|
98da24 |
index 0dd059f..6e201d5 100644
|
|
|
98da24 |
--- a/driver/my_stmt.c
|
|
|
98da24 |
+++ b/driver/my_stmt.c
|
|
|
98da24 |
@@ -44,7 +44,16 @@ BOOL returned_result(STMT *stmt)
|
|
|
98da24 |
if (ssps_used(stmt))
|
|
|
98da24 |
{
|
|
|
98da24 |
/* Basically at this point we are supposed to get result already */
|
|
|
98da24 |
- return stmt->result ? TRUE : mysql_stmt_result_metadata(stmt->ssps) != NULL;
|
|
|
98da24 |
+ MYSQL_RES *temp_res= NULL;
|
|
|
98da24 |
+
|
|
|
98da24 |
+ if ((stmt->result != NULL) ||
|
|
|
98da24 |
+ (temp_res= mysql_stmt_result_metadata(stmt->ssps)) != NULL)
|
|
|
98da24 |
+ {
|
|
|
98da24 |
+ /* mysql_free_result checks for NULL, so we can always call it */
|
|
|
98da24 |
+ mysql_free_result(temp_res);
|
|
|
98da24 |
+ return TRUE;
|
|
|
98da24 |
+ }
|
|
|
98da24 |
+ return FALSE;
|
|
|
98da24 |
}
|
|
|
98da24 |
else
|
|
|
98da24 |
{
|
|
|
98da24 |
@@ -55,24 +64,18 @@ BOOL returned_result(STMT *stmt)
|
|
|
98da24 |
|
|
|
98da24 |
my_bool free_current_result(STMT *stmt)
|
|
|
98da24 |
{
|
|
|
98da24 |
+ my_bool res= 0;
|
|
|
98da24 |
if (returned_result(stmt))
|
|
|
98da24 |
{
|
|
|
98da24 |
if (ssps_used(stmt))
|
|
|
98da24 |
-
|
|
|
98da24 |
- {
|
|
|
98da24 |
- my_bool res= mysql_stmt_free_result(stmt->ssps);
|
|
|
98da24 |
- stmt->result= NULL;
|
|
|
98da24 |
-
|
|
|
98da24 |
- return res;
|
|
|
98da24 |
- }
|
|
|
98da24 |
- else
|
|
|
98da24 |
{
|
|
|
98da24 |
- mysql_free_result(stmt->result);
|
|
|
98da24 |
- stmt->result= NULL;
|
|
|
98da24 |
- return '\0';
|
|
|
98da24 |
+ res= mysql_stmt_free_result(stmt->ssps);
|
|
|
98da24 |
}
|
|
|
98da24 |
+ /* We need to always free stmt->result because SSPS keep metadata there */
|
|
|
98da24 |
+ mysql_free_result(stmt->result);
|
|
|
98da24 |
+ stmt->result= NULL;
|
|
|
98da24 |
}
|
|
|
98da24 |
- return '\0';
|
|
|
98da24 |
+ return res;
|
|
|
98da24 |
}
|
|
|
98da24 |
|
|
|
98da24 |
|
|
|
98da24 |
@@ -98,6 +101,9 @@ MYSQL_RES * stmt_get_result(STMT *stmt, BOOL force_use)
|
|
|
98da24 |
we need to use/store each resultset of multiple resultsets */
|
|
|
98da24 |
MYSQL_RES * get_result_metadata(STMT *stmt, BOOL force_use)
|
|
|
98da24 |
{
|
|
|
98da24 |
+ /* just a precaution, mysql_free_result checks for NULL anywat */
|
|
|
98da24 |
+ mysql_free_result(stmt->result);
|
|
|
98da24 |
+
|
|
|
98da24 |
if (ssps_used(stmt))
|
|
|
98da24 |
{
|
|
|
98da24 |
stmt->result= mysql_stmt_result_metadata(stmt->ssps);
|
|
|
98da24 |
@@ -399,6 +405,9 @@ SQLRETURN prepare(STMT *stmt, char * query, SQLINTEGER query_length)
|
|
|
98da24 |
|
|
|
98da24 |
stmt->param_count= mysql_stmt_param_count(stmt->ssps);
|
|
|
98da24 |
|
|
|
98da24 |
+ /* make sure we free the result from the previous time */
|
|
|
98da24 |
+ mysql_free_result(stmt->result);
|
|
|
98da24 |
+
|
|
|
98da24 |
/* Getting result metadata */
|
|
|
98da24 |
if ((stmt->result= mysql_stmt_result_metadata(stmt->ssps)))
|
|
|
98da24 |
{
|
|
|
98da24 |
--
|
|
|
98da24 |
2.13.3
|
|
|
98da24 |
|