Commit 17bbe30c authored by Tatiana A. Nurnberg's avatar Tatiana A. Nurnberg

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.
parent 8d16eb71
...@@ -593,3 +593,13 @@ select str_to_date('04/30/2004 ', '%m/%d/%Y '); ...@@ -593,3 +593,13 @@ select str_to_date('04/30/2004 ', '%m/%d/%Y ');
str_to_date('04/30/2004 ', '%m/%d/%Y ') str_to_date('04/30/2004 ', '%m/%d/%Y ')
2004-04-30 2004-04-30
"End of 4.1 tests" "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"
...@@ -337,3 +337,15 @@ select str_to_date('04/30 /2004', '%m /%d /%Y'); ...@@ -337,3 +337,15 @@ select str_to_date('04/30 /2004', '%m /%d /%Y');
select str_to_date('04/30/2004 ', '%m/%d/%Y '); select str_to_date('04/30/2004 ', '%m/%d/%Y ');
--echo "End of 4.1 tests" --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"
...@@ -765,19 +765,20 @@ long calc_daynr(uint year,uint month,uint day) ...@@ -765,19 +765,20 @@ long calc_daynr(uint year,uint month,uint day)
{ {
long delsum; long delsum;
int temp; int temp;
int y= year; /* may be < 0 temporarily */
DBUG_ENTER("calc_daynr"); DBUG_ENTER("calc_daynr");
if (year == 0 && month == 0 && day == 0) if (y == 0 && month == 0 && day == 0)
DBUG_RETURN(0); /* Skip errors */ DBUG_RETURN(0); /* Skip errors */
delsum= (long) (365L * year+ 31*(month-1) +day); delsum= (long) (365L * y+ 31*(month-1) +day);
if (month <= 2) if (month <= 2)
year--; y--;
else else
delsum-= (long) (month*4+23)/10; 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", DBUG_PRINT("exit",("year: %d month: %d day: %d -> daynr: %ld",
year+(month <= 2),month,day,delsum+year/4-temp)); y+(month <= 2),month,day,delsum+y/4-temp));
DBUG_RETURN(delsum+(int) year/4-temp); DBUG_RETURN(delsum+(int) y/4-temp);
} /* calc_daynr */ } /* calc_daynr */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment