List:Commits« Previous MessageNext Message »
From:Tatiana A. Nurnberg Date:January 8 2009 9:25am
Subject:bzr commit into mysql-5.0-bugteam branch (azundris:2725) Bug#41470
View as plain text  
#At file:///misc/mysql/forest/41470/50-41470/ based on revid:joro@stripped

 2725 Tatiana A. Nurnberg	2009-01-08
      Bug#41470: DATE_FORMAT() crashes the complete server with a valid date
      
      Passing dubious "year zero" in non-zero date (not "0000-00-00") could
      lead to negative value for year internally, while variable was unsigned.
      This led to Really Bad Things further down the line.
      
      Now doing calculations with signed type for year internally.
modified:
  mysql-test/r/date_formats.result
  mysql-test/t/date_formats.test
  sql-common/my_time.c

per-file messages:
  mysql-test/r/date_formats.result
    show that very early dates no longer break DATE_FORMAT(..., '%W')
  mysql-test/t/date_formats.test
    show that very early dates no longer break DATE_FORMAT(..., '%W')
  sql-common/my_time.c
    Allow negative years numbers internally while keeping the interface.
    otherwise if somebody passes year zero for whatever reason, we'll
    get an integer wrap-around that can lead to Really Bad Things further
    down the line. Note that amusingly, calcday_nr() already had signed
    output and calc_weekday() already had signed input, anyway.
=== modified file 'mysql-test/r/date_formats.result'
--- a/mysql-test/r/date_formats.result	2007-09-22 07:49:27 +0000
+++ b/mysql-test/r/date_formats.result	2009-01-08 09:25:31 +0000
@@ -593,3 +593,13 @@ select str_to_date('04/30/2004 ', '%m/%d
 str_to_date('04/30/2004 ', '%m/%d/%Y ')
 2004-04-30
 "End of 4.1 tests"
+SELECT DATE_FORMAT("0000-01-01",'%W %d %M %Y') as valid_date;
+valid_date
+Sunday 01 January 0000
+SELECT DATE_FORMAT("0000-02-28",'%W %d %M %Y') as valid_date;
+valid_date
+Tuesday 28 February 0000
+SELECT DATE_FORMAT("2009-01-01",'%W %d %M %Y') as valid_date;
+valid_date
+Thursday 01 January 2009
+"End of 5.0 tests"

=== modified file 'mysql-test/t/date_formats.test'
--- a/mysql-test/t/date_formats.test	2007-05-16 08:44:59 +0000
+++ b/mysql-test/t/date_formats.test	2009-01-08 09:25:31 +0000
@@ -337,3 +337,15 @@ select str_to_date('04/30 /2004', '%m /%
 select str_to_date('04/30/2004 ', '%m/%d/%Y ');
 
 --echo "End of 4.1 tests"
+
+#
+# Bug #41470: DATE_FORMAT() crashes the complete server with a valid date
+#
+
+# show that these two do not crash the server:
+SELECT DATE_FORMAT("0000-01-01",'%W %d %M %Y') as valid_date;
+SELECT DATE_FORMAT("0000-02-28",'%W %d %M %Y') as valid_date;
+# show that date within the Gregorian range render correct results: (THU)
+SELECT DATE_FORMAT("2009-01-01",'%W %d %M %Y') as valid_date;
+
+--echo "End of 5.0 tests"

=== modified file 'sql-common/my_time.c'
--- a/sql-common/my_time.c	2008-04-03 15:32:00 +0000
+++ b/sql-common/my_time.c	2009-01-08 09:25:31 +0000
@@ -765,19 +765,20 @@ long calc_daynr(uint year,uint month,uin
 {
   long delsum;
   int temp;
+  int y= year;                                  /* may be < 0 temporarily */
   DBUG_ENTER("calc_daynr");
 
-  if (year == 0 && month == 0 && day == 0)
+  if (y == 0 && month == 0 && day == 0)
     DBUG_RETURN(0);				/* Skip errors */
-  delsum= (long) (365L * year+ 31*(month-1) +day);
+  delsum= (long) (365L * y+ 31*(month-1) +day);
   if (month <= 2)
-      year--;
+      y--;
   else
     delsum-= (long) (month*4+23)/10;
-  temp=(int) ((year/100+1)*3)/4;
+  temp=(int) ((y/100+1)*3)/4;
   DBUG_PRINT("exit",("year: %d  month: %d  day: %d -> daynr: %ld",
-		     year+(month <= 2),month,day,delsum+year/4-temp));
-  DBUG_RETURN(delsum+(int) year/4-temp);
+		     y+(month <= 2),month,day,delsum+y/4-temp));
+  DBUG_RETURN(delsum+(int) y/4-temp);
 } /* calc_daynr */
 
 

Thread
bzr commit into mysql-5.0-bugteam branch (azundris:2725) Bug#41470Tatiana A. Nurnberg8 Jan