Commit a81a0158 authored by Alexey Kopytov's avatar Alexey Kopytov

Pull from mysql-5.0-bugteam.

parents 684218b0 84de3b93
...@@ -85,6 +85,7 @@ class Materialized_cursor: public Server_side_cursor ...@@ -85,6 +85,7 @@ class Materialized_cursor: public Server_side_cursor
List<Item> item_list; List<Item> item_list;
ulong fetch_limit; ulong fetch_limit;
ulong fetch_count; ulong fetch_count;
bool is_rnd_inited;
public: public:
Materialized_cursor(select_result *result, TABLE *table); Materialized_cursor(select_result *result, TABLE *table);
...@@ -191,7 +192,11 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, ...@@ -191,7 +192,11 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
such command is SHOW VARIABLES or SHOW STATUS. such command is SHOW VARIABLES or SHOW STATUS.
*/ */
if (rc) if (rc)
{
if (result_materialize->materialized_cursor)
delete result_materialize->materialized_cursor;
goto err_open; goto err_open;
}
if (sensitive_cursor->is_open()) if (sensitive_cursor->is_open())
{ {
...@@ -532,7 +537,8 @@ Materialized_cursor::Materialized_cursor(select_result *result_arg, ...@@ -532,7 +537,8 @@ Materialized_cursor::Materialized_cursor(select_result *result_arg,
:Server_side_cursor(&table_arg->mem_root, result_arg), :Server_side_cursor(&table_arg->mem_root, result_arg),
table(table_arg), table(table_arg),
fetch_limit(0), fetch_limit(0),
fetch_count(0) fetch_count(0),
is_rnd_inited(0)
{ {
fake_unit.init_query(); fake_unit.init_query();
fake_unit.thd= table->in_use; fake_unit.thd= table->in_use;
...@@ -589,11 +595,12 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) ...@@ -589,11 +595,12 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused)))
THD *thd= fake_unit.thd; THD *thd= fake_unit.thd;
int rc; int rc;
Query_arena backup_arena; Query_arena backup_arena;
thd->set_n_backup_active_arena(this, &backup_arena); thd->set_n_backup_active_arena(this, &backup_arena);
/* Create a list of fields and start sequential scan */ /* Create a list of fields and start sequential scan */
rc= (result->prepare(item_list, &fake_unit) || rc= result->prepare(item_list, &fake_unit);
table->file->ha_rnd_init(TRUE)); if (!rc && !(rc= table->file->ha_rnd_init(TRUE)))
is_rnd_inited= 1;
thd->restore_active_arena(this, &backup_arena); thd->restore_active_arena(this, &backup_arena);
if (rc == 0) if (rc == 0)
{ {
...@@ -673,7 +680,8 @@ void Materialized_cursor::close() ...@@ -673,7 +680,8 @@ void Materialized_cursor::close()
{ {
/* Free item_list items */ /* Free item_list items */
free_items(); free_items();
(void) table->file->ha_rnd_end(); if (is_rnd_inited)
(void) table->file->ha_rnd_end();
/* /*
We need to grab table->mem_root to prevent free_tmp_table from freeing: We need to grab table->mem_root to prevent free_tmp_table from freeing:
the cursor object was allocated in this memory. the cursor object was allocated in this memory.
......
...@@ -1599,8 +1599,11 @@ JOIN::exec() ...@@ -1599,8 +1599,11 @@ JOIN::exec()
(zero_result_cause?zero_result_cause:"No tables used")); (zero_result_cause?zero_result_cause:"No tables used"));
else else
{ {
result->send_fields(*columns_list, if (result->send_fields(*columns_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
{
DBUG_VOID_RETURN;
}
/* /*
We have to test for 'conds' here as the WHERE may not be constant We have to test for 'conds' here as the WHERE may not be constant
even if we don't have any tables for prepared statements or if even if we don't have any tables for prepared statements or if
......
...@@ -15899,6 +15899,59 @@ static void test_bug28934() ...@@ -15899,6 +15899,59 @@ static void test_bug28934()
} }
/**
Bug#37956 memory leak and / or crash with geometry and prepared statements!
*/
static void test_bug37956(void)
{
const char *query="select point(?,?)";
MYSQL_STMT *stmt=NULL;
unsigned int val=0;
MYSQL_BIND bind_param[2];
unsigned char buff[2]= { 134, 211 };
DBUG_ENTER("test_bug37956");
myheader("test_bug37956");
stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
val=1;
mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void *)&val);
val=CURSOR_TYPE_READ_ONLY;
mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void *)&val);
val=0;
mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, (void *)&val);
memset(bind_param, 0, sizeof(bind_param));
bind_param[0].buffer_type=MYSQL_TYPE_TINY;
bind_param[0].buffer= (void *)buff;
bind_param[0].is_null=NULL;
bind_param[0].error=NULL;
bind_param[0].is_unsigned=1;
bind_param[1].buffer_type=MYSQL_TYPE_TINY;
bind_param[1].buffer= (void *)(buff+1);
bind_param[1].is_null=NULL;
bind_param[1].error=NULL;
bind_param[1].is_unsigned=1;
if (mysql_stmt_bind_param(stmt, bind_param))
{
mysql_stmt_close(stmt);
DIE_UNLESS(0);
}
if (mysql_stmt_execute(stmt))
{
mysql_stmt_close(stmt);
DBUG_VOID_RETURN;
}
/* Should never reach here: execution returns an error. */
mysql_stmt_close(stmt);
DIE_UNLESS(0);
DBUG_VOID_RETURN;
}
/* /*
Bug#27592 (stack overrun when storing datetime value using prepared statements) Bug#27592 (stack overrun when storing datetime value using prepared statements)
*/ */
...@@ -16595,6 +16648,7 @@ static struct my_tests_st my_tests[]= { ...@@ -16595,6 +16648,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug32265", test_bug32265 }, { "test_bug32265", test_bug32265 },
{ "test_bug38486", test_bug38486 }, { "test_bug38486", test_bug38486 },
{ "test_bug40365", test_bug40365 }, { "test_bug40365", test_bug40365 },
{ "test_bug37956", test_bug37956 },
{ 0, 0 } { 0, 0 }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment