List:Commits« Previous MessageNext Message »
From:Alexander Barkov Date:January 13 2012 8:37am
Subject:bzr push into mysql-trunk branch (alexander.barkov:3726 to 3727) Bug#13354387
View as plain text  
 3727 Alexander Barkov	2012-01-13
      BUG#13354387 - CRASH IN IN MY_DECIMAL::OPERATOR FOR VIEW AND FUNCTION UNIX_TIME
      Fixing the 5.6 part (the 5.5 was earlier committed in a separate commit).
      
      Problem:
      UNIX_TIMESTAMP() could return NULL in case of maybe_null==0.
      
      Fix:
      
      Moving NULL/0 decision logic from 
      Item_func_unix_timestamp::val_timeval()
      to
      Item::get_timeval()
      Item_field::get_timeval()

    modified:
      mysql-test/r/func_time.result
      mysql-test/t/func_time.test
      sql/item.cc
      sql/item_timefunc.cc
 3726 Tor Didriksen	2012-01-12 [merge]
      empty merge 5.5 => trunk

=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result	2012-01-12 13:27:57 +0000
+++ b/mysql-test/r/func_time.result	2012-01-13 08:36:43 +0000
@@ -1505,3 +1505,31 @@ select 1 from t1 where 1 < some (select
 1
 1
 drop table t1;
+#
+# End of 5.5 tests
+#
+#
+# Start of 5.6 tests
+#
+#
+# BUG#13354387 - CRASH IN IN MY_DECIMAL::OPERATOR FOR VIEW AND FUNCTION UNIX_TIMESTAMP 
+# Part2 (5.6)
+CREATE TABLE t1 (a VARCHAR(32) NOT NULL);
+INSERT INTO t1 VALUES ('a');
+SELECT 1 FROM t1 GROUP BY @a:=UNIX_TIMESTAMP(a);
+1
+1
+Warnings:
+Warning	1292	Incorrect datetime value: 'a'
+SELECT a, UNIX_TIMESTAMP(a), UNIX_TIMESTAMP('a') FROM t1;
+a	UNIX_TIMESTAMP(a)	UNIX_TIMESTAMP('a')
+a	0.000000	0.000000
+Warnings:
+Warning	1292	Incorrect datetime value: 'a'
+Warning	1292	Incorrect datetime value: 'a'
+DELETE FROM t1;
+INSERT INTO t1 VALUES ('5000-01-01 00:00:00');
+SELECT a, UNIX_TIMESTAMP(a), UNIX_TIMESTAMP('5000-01-01 00:00:00') FROM t1;
+a	UNIX_TIMESTAMP(a)	UNIX_TIMESTAMP('5000-01-01 00:00:00')
+5000-01-01 00:00:00	0.000000	0
+DROP TABLE t1;

=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test	2012-01-12 13:27:57 +0000
+++ b/mysql-test/t/func_time.test	2012-01-13 08:36:43 +0000
@@ -995,3 +995,23 @@ create table t1(a time);
 insert into t1 values ('00:00:00'),('00:01:00');
 select 1 from t1 where 1 < some (select cast(a as datetime) from t1);
 drop table t1;
+
+--echo #
+--echo # End of 5.5 tests
+--echo #
+
+--echo #
+--echo # Start of 5.6 tests
+--echo #
+
+--echo #
+--echo # BUG#13354387 - CRASH IN IN MY_DECIMAL::OPERATOR FOR VIEW AND FUNCTION UNIX_TIMESTAMP 
+--echo # Part2 (5.6)
+CREATE TABLE t1 (a VARCHAR(32) NOT NULL);
+INSERT INTO t1 VALUES ('a');
+SELECT 1 FROM t1 GROUP BY @a:=UNIX_TIMESTAMP(a);
+SELECT a, UNIX_TIMESTAMP(a), UNIX_TIMESTAMP('a') FROM t1;
+DELETE FROM t1;
+INSERT INTO t1 VALUES ('5000-01-01 00:00:00');
+SELECT a, UNIX_TIMESTAMP(a), UNIX_TIMESTAMP('5000-01-01 00:00:00') FROM t1;
+DROP TABLE t1;

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2012-01-12 13:27:57 +0000
+++ b/sql/item.cc	2012-01-13 08:36:43 +0000
@@ -1378,12 +1378,27 @@ bool Item::get_time_from_non_temporal(MY
 }
 
 
+/*
+- Return NULL if argument is NULL.
+- Return zero if argument is not NULL, but we could not convert it to DATETIME.
+- Return zero if argument is not NULL and represents a valid DATETIME value,
+  but the value is out of the supported Unix timestamp range.
+*/
 bool Item::get_timeval(struct timeval *tm, int *warnings)
 {
   MYSQL_TIME ltime;
-  return (null_value=
-          (get_date(&ltime, TIME_FUZZY_DATE) ||
-           datetime_to_timeval(current_thd, &ltime, tm, warnings)));
+  if (get_date(&ltime, TIME_FUZZY_DATE))
+  {
+    if (null_value)
+      return true; /* Value is NULL */
+    goto zero; /* Could not extract date from the value */
+  }
+  if (datetime_to_timeval(current_thd, &ltime, tm, warnings))
+    goto zero; /* Value is out of the supported range */
+  return false; /* Value is a good Unix timestamp */
+zero:
+  tm->tv_sec= tm->tv_usec= 0;
+  return false;
 }
 
 
@@ -2670,8 +2685,11 @@ bool Item_field::get_time(MYSQL_TIME *lt
 
 bool Item_field::get_timeval(struct timeval *tm, int *warnings)
 {
-  return (null_value= (field->is_null() ||
-                       field->get_timestamp(tm, warnings)));
+  if ((null_value= field->is_null()))
+    return true;
+  if (field->get_timestamp(tm, warnings))
+    tm->tv_sec= tm->tv_usec= 0;
+  return false;
 }
 
 double Item_field::val_result()

=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc	2011-12-16 16:57:46 +0000
+++ b/sql/item_timefunc.cc	2012-01-13 08:36:43 +0000
@@ -1456,20 +1456,7 @@ bool Item_func_unix_timestamp::val_timev
     return false; // no args: null_value is set in constructor and is always 0.
   }
   int warnings= 0;
-  if (args[0]->get_timeval(tm, &warnings)) // Don't set null_value here
-  {
-    /*
-      We set null_value only if args[0]->get_date() invoked
-      inside args[0]->get_timeval() returned null,
-      which is indicated by "warnings == 0".
-      In case of wrong non-null datetime parameter we return 0.
-      "warnings" will not be equal to 0 in this case.
-    */
-    if (warnings == 0)
-      return (null_value= true);
-    tm->tv_sec= tm->tv_usec= 0;
-  }
-  return (null_value= false);
+  return (null_value= args[0]->get_timeval(tm, &warnings));
 }
 
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (alexander.barkov:3726 to 3727) Bug#13354387Alexander Barkov13 Jan