From 728000b22514f97cca66126c6f9e86a5ce7a0d61 Mon Sep 17 00:00:00 2001
From: "pem@mysql.comhem.se" <>
Date: Fri, 10 Sep 2004 16:28:11 +0200
Subject: [PATCH] Fixed BUG#4941: Stored procedure crash fetching null value
 into variable.

---
 mysql-test/r/sp.result | 16 ++++++++++++++++
 mysql-test/t/sp.test   | 22 ++++++++++++++++++++++
 sql/protocol_cursor.cc |  3 ++-
 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
@@ -2000,6 +2000,28 @@ select bug4487()|
 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())
-- 
2.30.9