List:Internals« Previous MessageNext Message »
From:Alex Ivanov Date:September 8 2005 4:59pm
Subject:bk commit into 5.0 tree (aivanov:1.1979) BUG#11655
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of alexi. When alexi does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1979 05/09/08 20:58:59 aivanov@stripped +3 -0
  Fix for BUG #11655  Time values are not always checked to lie in
  the TIME range
   

  sql/item_timefunc.cc
    1.94 05/09/08 20:58:50 aivanov@stripped +136 -0
    Added check_time_range().
    Modified Item_func_time_to_sec::val_int(),
     Item_func_sec_to_time::val_str(),
     Item_func_sec_to_time::val_int(),
     Item_func_add_time::val_str(),
     Item_func_make_time::val_str()
     

  mysql-test/t/func_time.test
    1.38 05/09/08 20:58:50 aivanov@stripped +20 -0
    Added testcases for bug #11655
     

  mysql-test/r/func_time.result
    1.46 05/09/08 20:58:50 aivanov@stripped +42 -0
    Fixed some testcases results (bug #11655)
     

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	aivanov
# Host:	mysql.creware.com
# Root:	/home/alexi/dev/mysql-5.0-0

--- 1.93/sql/item_timefunc.cc	2005-08-25 02:50:54 +04:00
+++ 1.94/sql/item_timefunc.cc	2005-09-08 20:58:50 +04:00
@@ -49,6 +49,130 @@
 
 
 /*
+  Check (hour,minute,second) triplet to lie in the TIME range
+
+  SYNOPSIS:
+    check_time_range()
+    hour      pointer to hours value
+    minute    pointer to minutes value
+    second    pointer to seconds value
+    warn      true if out of the TIME range warning should be produced
+
+  DESCRIPTION
+    If the triplet lies outside the range [-838:59:59, 838:59:59]
+    the function sets it to the closest endpoint of the range and 
+    in case of warn=true produces warning.
+
+  RETURN
+    0   the triplet lies in the range
+    1   the triplet lies outside the range and is set to new value
+*/
+
+inline int check_time_range(long *hour, long *minute, long *second, bool warn)
+{
+  if (abs(*hour) < 839)
+    return 0;
+
+  if (warn)
+  {
+    char buf[3*sizeof(long)+8];
+    my_snprintf(buf, sizeof(buf)-1, "%d:%02u:%02u", *hour, *minute, *second);
+    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+      ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), "TIME", buf);
+  }
+
+  *hour= (*hour < 0) ? -838 : 838;
+  *minute= 59;
+  *second= 59;
+  return 1;
+}
+
+
+/*
+  Check TIME value to lie in the TIME range
+
+  SYNOPSIS:
+    check_time_range()
+    time    pointer to TIME value
+    warn    true if out of the TIME range warning should be produced
+
+  DESCRIPTION
+    If the time value lies outside the range [-838:59:59, 838:59:59]
+    the function sets it to the closest endpoint of the range and 
+    in case of warn=true produces warning.
+
+  RETURN
+    0   the time value lies in the range
+    1   the time value lies outside the range and is set to new value
+*/
+
+inline int check_time_range(TIME *time, bool warn)
+{
+  if (time->time_type != MYSQL_TIMESTAMP_TIME)
+    return 0;
+
+  long hour= time->hour + (24*time->day);
+  if ((hour < 839) &&
+      (hour != 838 || time->minute != 59 || time->second != 59 ||
+       !time->second_part))
+    return 0;
+
+  if (warn)
+  {
+    char buf[9*sizeof(long) + 11];
+    my_snprintf(buf, sizeof(buf)-1, "%s%u %u:%02u:%02u.%u",
+      time->neg ? "- " : "", time->day, time->hour,
+      time->minute, time->second, time->second_part);
+    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+      ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), "TIME", buf);
+  }
+
+  time->day= 0;
+  time->hour= 838;
+  time->minute= 59;
+  time->second= 59;
+  time->second_part= 0;
+  return 1;
+}
+
+
+/*
+  Check seconds to lie in the TIME range
+
+  SYNOPSIS:
+    check_time_range()
+    seconds   pointer to seconds value
+    warn      true if out of the TIME range warning should be produced
+
+  DESCRIPTION
+    If the seconds value lies outside the range [-838:59:59, 838:59:59]
+    the function sets it to the closest endpoint of the range and 
+    in case of warn=true produces warning.
+
+  RETURN
+    0   the seconds value lies in the range
+    1   the seconds value lies outside the range and is set to new value
+*/
+
+inline int check_time_range(longlong *seconds, bool warn)
+{
+  if (abs(*seconds) <= 3020399) /*[-838:59:59, 838:59:59]*/
+    return 0;
+
+  if (warn)
+  {
+    char buf[22];
+    longlong10_to_str(*seconds, buf, -10);
+    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+      ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), "TIME", buf);
+  }
+
+  *seconds= (*seconds < 0) ? -3020399 : 3020399;
+  return 0;
+}
+
+
+/*
   OPTIMIZATION TODO:
    - Replace the switch with a function that should be called for each
      date type.
@@ -1103,6 +1227,7 @@
   TIME ltime;
   longlong seconds;
   (void) get_arg0_time(&ltime);
+  check_time_range(&ltime, 1);
   seconds=ltime.hour*3600L+ltime.minute*60+ltime.second;
   return ltime.neg ? -seconds : seconds;
 }
@@ -1568,6 +1693,8 @@
     return (String*) 0;
   }
 
+  check_time_range(&seconds, 1);
+
   ltime.neg= 0;
   if (seconds < 0)
   {
@@ -1593,6 +1720,7 @@
   longlong sign=1;
   if ((null_value=args[0]->null_value))
     return 0;
+  check_time_range(&seconds, 1);
   if (seconds < 0)
   {
     seconds= -seconds;
@@ -2535,6 +2663,9 @@
       goto null_date;
     is_time= (l_time1.time_type == MYSQL_TIMESTAMP_TIME);
   }
+  check_time_range(&l_time1, 1);
+  check_time_range(&l_time2, 1);
+
   if (l_time1.neg != l_time2.neg)
     l_sign= -l_sign;
 
@@ -2566,6 +2697,9 @@
   }
   
   l_time3.hour+= days*24;
+  l_time3.day= 0;
+  l_time3.time_type= MYSQL_TIMESTAMP_TIME;
+  check_time_range(&l_time3, 1);
   if (!make_datetime(l_time1.second_part || l_time2.second_part ?
 		     TIME_MICROSECOND : TIME_ONLY,
 		     &l_time3, str))
@@ -2668,6 +2802,8 @@
 		   second > 59 || second < 0 ||
 		   str->alloc(19))))
     return 0;
+
+  check_time_range(&hour, &minute, &second, 1);
 
   ltime.neg= 0;
   if (hour < 0)

--- 1.45/mysql-test/r/func_time.result	2005-08-25 02:50:54 +04:00
+++ 1.46/mysql-test/r/func_time.result	2005-09-08 20:58:50 +04:00
@@ -760,3 +760,45 @@
 @a != @b
 1
 drop procedure t_sysdate;
+SELECT SEC_TO_TIME(3020399);
+SEC_TO_TIME(3020399)
+838:59:59
+SELECT SEC_TO_TIME(3300000);
+SEC_TO_TIME(3300000)
+838:59:59
+Warnings:
+Warning	1292	Truncated incorrect TIME value: '3300000'
+SELECT TIME_TO_SEC('838:59:59');
+TIME_TO_SEC('838:59:59')
+3020399
+SELECT TIME_TO_SEC('916:40:00');
+TIME_TO_SEC('916:40:00')
+3020399
+Warnings:
+Warning	1292	Truncated incorrect TIME value: '0 916:40:00.0'
+SELECT MAKETIME(916,40,00);
+MAKETIME(916,40,00)
+838:59:59
+Warnings:
+Warning	1292	Truncated incorrect TIME value: '916:40:00'
+SELECT ADDTIME('500:00:00', '416:40:00');
+ADDTIME('500:00:00', '416:40:00')
+838:59:59
+Warnings:
+Warning	1292	Truncated incorrect TIME value: '0 916:40:00.0'
+SELECT ADDTIME('838:59:59', '-416:40:00');
+ADDTIME('838:59:59', '-416:40:00')
+422:19:59
+SELECT ADDTIME('916:40:00', '-416:40:00');
+ADDTIME('916:40:00', '-416:40:00')
+422:19:59
+Warnings:
+Warning	1292	Truncated incorrect TIME value: '0 916:40:00.0'
+SELECT SUBTIME('838:59:59', '416:40:00');
+SUBTIME('838:59:59', '416:40:00')
+422:19:59
+SELECT SUBTIME('916:40:00', '416:40:00');
+SUBTIME('916:40:00', '416:40:00')
+422:19:59
+Warnings:
+Warning	1292	Truncated incorrect TIME value: '0 916:40:00.0'

--- 1.37/mysql-test/t/func_time.test	2005-08-25 02:50:54 +04:00
+++ 1.38/mysql-test/t/func_time.test	2005-09-08 20:58:50 +04:00
@@ -404,4 +404,24 @@
 call t_sysdate();
 drop procedure t_sysdate;
 
+#
+# Test for bug #11655: time is not always checked to lie in the TIME range
+#
+
+SELECT SEC_TO_TIME(3020399);
+SELECT SEC_TO_TIME(3300000);
+
+SELECT TIME_TO_SEC('838:59:59');
+SELECT TIME_TO_SEC('916:40:00');
+
+SELECT MAKETIME(916,40,00);
+
+SELECT ADDTIME('500:00:00', '416:40:00');
+
+SELECT ADDTIME('838:59:59', '-416:40:00');
+SELECT ADDTIME('916:40:00', '-416:40:00');
+
+SELECT SUBTIME('838:59:59', '416:40:00');
+SELECT SUBTIME('916:40:00', '416:40:00');
+
 # End of 5.0 tests
Thread
bk commit into 5.0 tree (aivanov:1.1979) BUG#11655Alex Ivanov8 Sep