summaryrefslogtreecommitdiff
path: root/sql-common
diff options
context:
space:
mode:
authorTatiana A. Nurnberg <azundris@mysql.com>2009-01-08 10:25:31 +0100
committerTatiana A. Nurnberg <azundris@mysql.com>2009-01-08 10:25:31 +0100
commitc42892d61413adea81c174a90d458c07a8ddd52c (patch)
tree852b3f5c961cbd640ea97deb0fed925abe3ba174 /sql-common
parent374f49b2629114a9473268da4321af405a9d2394 (diff)
downloadmariadb-git-c42892d61413adea81c174a90d458c07a8ddd52c.tar.gz
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. 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.
Diffstat (limited to 'sql-common')
-rw-r--r--sql-common/my_time.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 1781251fca1..16a64ebd947 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -765,19 +765,20 @@ long calc_daynr(uint year,uint month,uint day)
{
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 */