diff options
-rw-r--r-- | mysql-test/r/sp.result | 16 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 22 | ||||
-rw-r--r-- | sql/protocol_cursor.cc | 3 | ||||
-rw-r--r-- | sql/sp_rcontext.cc | 27 |
4 files changed, 55 insertions, 13 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 6d743bf5c71..f84b224b8e0 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1833,6 +1833,22 @@ NULL Warnings: Warning 1311 Referring to uninitialized variable v drop function bug4487| +drop procedure if exists bug4941| +create procedure bug4941(out x int) +begin +declare c cursor for select i from t2 limit 1; +open c; +fetch c into x; +close c; +end| +insert into t2 values (null, null, null)| +set @x = 42| +call bug4941(@x)| +select @x| +@x +NULL +delete from t1| +drop procedure bug4941| drop table if exists fac| create table fac (n int unsigned not null primary key, f bigint unsigned)| create procedure ifac(n int unsigned) diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 1d7efab3841..e2c82c9f0da 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -2001,6 +2001,28 @@ drop function bug4487| # +# BUG#4941: Stored procedure crash fetching null value into variable. +# +--disable_warnings +drop procedure if exists bug4941| +--enable_warnings +create procedure bug4941(out x int) +begin + declare c cursor for select i from t2 limit 1; + open c; + fetch c into x; + close c; +end| + +insert into t2 values (null, null, null)| +set @x = 42| +call bug4941(@x)| +select @x| +delete from t1| +drop procedure bug4941| + + +# # Some "real" examples # diff --git a/sql/protocol_cursor.cc b/sql/protocol_cursor.cc index 31eaa894045..8904aba7b88 100644 --- a/sql/protocol_cursor.cc +++ b/sql/protocol_cursor.cc @@ -112,7 +112,8 @@ bool Protocol_cursor::write() for (; cur_field < fields_end; ++cur_field, ++data_tmp) { - if ((len= net_field_length((uchar **)&cp)) == 0) + if ((len= net_field_length((uchar **)&cp)) == 0 || + len == NULL_LENGTH) { *data_tmp= 0; } diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 1bdd022470b..2f7bdbffa2b 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -230,21 +230,24 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars) return -1; } s= row[fldcount]; - switch (sp_map_result_type(pv->type)) - { - case INT_RESULT: - it= new Item_int(s); - break; - case REAL_RESULT: - it= new Item_real(s, strlen(s)); - break; - default: + if (!s) + it= new Item_null(); + else + switch (sp_map_result_type(pv->type)) { - uint len= strlen(s); - it= new Item_string(thd->strmake(s, len), len, thd->db_charset); + case INT_RESULT: + it= new Item_int(s); break; + case REAL_RESULT: + it= new Item_real(s, strlen(s)); + break; + default: + { + uint len= strlen(s); + it= new Item_string(thd->strmake(s, len), len, thd->db_charset); + break; + } } - } thd->spcont->set_item(pv->offset, it); } if (fldcount < m_prot->get_field_count()) |