mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
Fix for bug #24117 "server crash on a FETCH with a cursor on a table which is not in the table cache"
Problem: When creating a temporary field for a temporary table in create_tmp_field_from_field(), a resulting field is created as an exact copy of an original one (in Field::new_field()). However, Field_enum and Field_set contain a pointer (typelib) to memory allocated in the parent table's MEM_ROOT, which under some circumstances may be deallocated later by the time a temporary table is used. Solution: Override the new_field() method for Field_enum and Field_set and create a separate copy of the typelib structure in there. include/typelib.h: Added copy_typelib() declaration mysql-test/r/sp.result: Added a testcase for bug #24117 "server crash on a FETCH with a cursor on a table which is not in the table cache" mysql-test/t/sp.test: Added a testcase for bug #24117 "server crash on a FETCH with a cursor on a table which is not in the table cache" mysys/typelib.c: Added copy_typelib() definition sql/field.cc: Create a copy of the internal 'typelib' structure when copying Field_enum of Field_set objects. sql/field.h: Override new_field method in Field_enum (and Field_set) to copy the typelib structure.
This commit is contained in:
parent
66e49e3763
commit
5b71281467
6 changed files with 105 additions and 0 deletions
|
@ -18,6 +18,8 @@
|
|||
#ifndef _typelib_h
|
||||
#define _typelib_h
|
||||
|
||||
#include "my_alloc.h"
|
||||
|
||||
typedef struct st_typelib { /* Different types saved here */
|
||||
unsigned int count; /* How many types */
|
||||
const char *name; /* Name of typelib */
|
||||
|
@ -28,6 +30,7 @@ typedef struct st_typelib { /* Different types saved here */
|
|||
extern int find_type(char *x,TYPELIB *typelib,unsigned int full_name);
|
||||
extern void make_type(char *to,unsigned int nr,TYPELIB *typelib);
|
||||
extern const char *get_type(TYPELIB *typelib,unsigned int nr);
|
||||
extern TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from);
|
||||
|
||||
extern TYPELIB sql_protocol_typelib;
|
||||
|
||||
|
|
|
@ -5708,4 +5708,20 @@ DROP TABLE bug23760, bug23760_log|
|
|||
DROP PROCEDURE bug23760_update_log|
|
||||
DROP PROCEDURE bug23760_test_row_count|
|
||||
DROP FUNCTION bug23760_rc_test|
|
||||
DROP PROCEDURE IF EXISTS bug24117|
|
||||
DROP TABLE IF EXISTS t3|
|
||||
CREATE TABLE t3(c1 ENUM('abc'))|
|
||||
INSERT INTO t3 VALUES('abc')|
|
||||
CREATE PROCEDURE bug24117()
|
||||
BEGIN
|
||||
DECLARE t3c1 ENUM('abc');
|
||||
DECLARE mycursor CURSOR FOR SELECT c1 FROM t3;
|
||||
OPEN mycursor;
|
||||
FLUSH TABLES;
|
||||
FETCH mycursor INTO t3c1;
|
||||
CLOSE mycursor;
|
||||
END|
|
||||
CALL bug24117()|
|
||||
DROP PROCEDURE bug24117|
|
||||
DROP TABLE t3|
|
||||
drop table t1,t2;
|
||||
|
|
|
@ -6662,6 +6662,30 @@ DROP PROCEDURE bug23760_update_log|
|
|||
DROP PROCEDURE bug23760_test_row_count|
|
||||
DROP FUNCTION bug23760_rc_test|
|
||||
|
||||
#
|
||||
# BUG#24117: server crash on a FETCH with a cursor on a table which is not in
|
||||
# the table cache
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
DROP PROCEDURE IF EXISTS bug24117|
|
||||
DROP TABLE IF EXISTS t3|
|
||||
--enable_warnings
|
||||
CREATE TABLE t3(c1 ENUM('abc'))|
|
||||
INSERT INTO t3 VALUES('abc')|
|
||||
CREATE PROCEDURE bug24117()
|
||||
BEGIN
|
||||
DECLARE t3c1 ENUM('abc');
|
||||
DECLARE mycursor CURSOR FOR SELECT c1 FROM t3;
|
||||
OPEN mycursor;
|
||||
FLUSH TABLES;
|
||||
FETCH mycursor INTO t3c1;
|
||||
CLOSE mycursor;
|
||||
END|
|
||||
CALL bug24117()|
|
||||
DROP PROCEDURE bug24117|
|
||||
DROP TABLE t3|
|
||||
|
||||
#
|
||||
# NOTE: The delimiter is `|`, and not `;`. It is changed to `;`
|
||||
# at the end of the file!
|
||||
|
|
|
@ -119,3 +119,54 @@ const char *get_type(TYPELIB *typelib, uint nr)
|
|||
return(typelib->type_names[nr]);
|
||||
return "?";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create a copy of a specified TYPELIB structure.
|
||||
|
||||
SYNOPSIS
|
||||
copy_typelib()
|
||||
root pointer to a MEM_ROOT object for allocations
|
||||
from pointer to a source TYPELIB structure
|
||||
|
||||
RETURN
|
||||
pointer to the new TYPELIB structure on successful copy, or
|
||||
NULL otherwise
|
||||
*/
|
||||
|
||||
TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from)
|
||||
{
|
||||
TYPELIB *to;
|
||||
uint i;
|
||||
|
||||
if (!from)
|
||||
return NULL;
|
||||
|
||||
if (!(to= (TYPELIB*) alloc_root(root, sizeof(TYPELIB))))
|
||||
return NULL;
|
||||
|
||||
if (!(to->type_names= (const char **)
|
||||
alloc_root(root, (sizeof(char *) + sizeof(int)) * (from->count + 1))))
|
||||
return NULL;
|
||||
to->type_lengths= (unsigned int *)(to->type_names + from->count + 1);
|
||||
to->count= from->count;
|
||||
if (from->name)
|
||||
{
|
||||
if (!(to->name= strdup_root(root, from->name)))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
to->name= NULL;
|
||||
|
||||
for (i= 0; i < from->count; i++)
|
||||
{
|
||||
if (!(to->type_names[i]= strmake_root(root, from->type_names[i],
|
||||
from->type_lengths[i])))
|
||||
return NULL;
|
||||
to->type_lengths[i]= from->type_lengths[i];
|
||||
}
|
||||
to->type_names[to->count]= NULL;
|
||||
to->type_lengths[to->count]= 0;
|
||||
|
||||
return to;
|
||||
}
|
||||
|
|
10
sql/field.cc
10
sql/field.cc
|
@ -7672,6 +7672,16 @@ void Field_enum::sql_type(String &res) const
|
|||
}
|
||||
|
||||
|
||||
Field *Field_enum::new_field(MEM_ROOT *root, struct st_table *new_table,
|
||||
bool keep_type)
|
||||
{
|
||||
Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
|
||||
if (res)
|
||||
res->typelib= copy_typelib(root, typelib);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
set type.
|
||||
This is a string which can have a collection of different values.
|
||||
|
|
|
@ -1277,6 +1277,7 @@ public:
|
|||
{
|
||||
flags|=ENUM_FLAG;
|
||||
}
|
||||
Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
|
||||
enum_field_types type() const { return FIELD_TYPE_STRING; }
|
||||
enum Item_result cmp_type () const { return INT_RESULT; }
|
||||
enum Item_result cast_to_int_type () const { return INT_RESULT; }
|
||||
|
|
Loading…
Reference in a new issue