Further changes to the date/time functions to suppress harmless signed
integer overflow warnings that could have occurred when doing out-of-range date calculations which, according to the docs, give undefined results. FossilOrigin-Name: dc453b3403450b1d8cc53daf0721fed025b9053c
This commit is contained in:
parent
3edb157e23
commit
d76a902c87
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C The\sdocumentation\ssays\sthat\sthe\sbuilt-in\sdate-time\sfunctions\sgive\sundefined\nresults\sfor\sdates\sbefore\s0000-01-01\sand\safter\s9999-12-31.\s\sChange\sthe\nactually\simplementation\sso\sthat\sthe\sanswer\sgiven\sis\sreally\sNULL.\s\sThis\salso\navoids\sunnecessary\shand-wringing\sover\san\ssigned\sinteger\soverflow\sthat\smight\notherwise\soccur\swhen\sprocessing\sout-of-bound\sdates.
|
||||
D 2016-11-29T20:39:48.413
|
||||
C Further\schanges\sto\sthe\sdate/time\sfunctions\sto\ssuppress\sharmless\ssigned\ninteger\soverflow\swarnings\sthat\scould\shave\soccurred\swhen\sdoing\sout-of-range\ndate\scalculations\swhich,\saccording\sto\sthe\sdocs,\sgive\sundefined\sresults.
|
||||
D 2016-11-30T00:48:28.495
|
||||
F Makefile.in 6b572807415d3f0a379cebc9461416d8df4a12c8
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc bb4d970894abbbe0e88d00aac29bd52af8bc95f4
|
||||
@ -337,7 +337,7 @@ F src/build.c 178f16698cbcb43402c343a9413fe22c99ffee21
|
||||
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c a2a52d6e353f459d8ab0f07321f60fafa47d5421
|
||||
F src/date.c 53a4019b90ae1c9cb990196eed0ed196d3f341e1
|
||||
F src/date.c 736c1f36c58bb137f64d8d1f72467dc027832563
|
||||
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
|
||||
F src/delete.c cac97d1117a3008934da3a6a587b3608e65e1495
|
||||
F src/expr.c 8c224aa28278a5c1eed55247b7a571ff388ad5c2
|
||||
@ -626,7 +626,7 @@ F test/csv01.test e0ba3caaa57e4c667a0b45977689fb8082f14348
|
||||
F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
|
||||
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
|
||||
F test/cursorhint2.test fa41f0d997e67db921d08c31e73111b32811201a
|
||||
F test/date.test 47e7f7057c0efac0e5e26da2d7b6a9a128139de6
|
||||
F test/date.test a6a5a48b90907bca9fbcc79a30be5a715c1ab2fc
|
||||
F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
|
||||
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
|
||||
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
|
||||
@ -1535,7 +1535,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 9021f6875f897d8b609ebcc04162dc6e0b529a4a
|
||||
R e95c6d806c4c5b465cfcf2c97462edc9
|
||||
P d410a839752153c6d8be08f758abfbc16475745a
|
||||
R 4de84d6de9c4735ca2171beb11da6949
|
||||
U drh
|
||||
Z f7a67f418429ef937fb437b96080796e
|
||||
Z a5d0c3a9dbd00d301630dafcf90b9504
|
||||
|
@ -1 +1 @@
|
||||
d410a839752153c6d8be08f758abfbc16475745a
|
||||
dc453b3403450b1d8cc53daf0721fed025b9053c
|
53
src/date.c
53
src/date.c
@ -65,17 +65,17 @@ struct tm *__cdecl localtime(const time_t *);
|
||||
*/
|
||||
typedef struct DateTime DateTime;
|
||||
struct DateTime {
|
||||
sqlite3_int64 iJD; /* The julian day number times 86400000 */
|
||||
int Y, M, D; /* Year, month, and day */
|
||||
int h, m; /* Hour and minutes */
|
||||
int tz; /* Timezone offset in minutes */
|
||||
double s; /* Seconds */
|
||||
char validYMD; /* True (1) if Y,M,D are valid */
|
||||
char validHMS; /* True (1) if h,m,s are valid */
|
||||
char validJD; /* True (1) if iJD is valid */
|
||||
char validTZ; /* True (1) if tz is valid */
|
||||
char tzSet; /* Timezone was set explicitly */
|
||||
char isError; /* An overflow has occurred */
|
||||
sqlite3_uint64 iJD; /* The julian day number times 86400000 */
|
||||
int Y, M, D; /* Year, month, and day */
|
||||
int h, m; /* Hour and minutes */
|
||||
int tz; /* Timezone offset in minutes */
|
||||
double s; /* Seconds */
|
||||
char validYMD; /* True (1) if Y,M,D are valid */
|
||||
char validHMS; /* True (1) if h,m,s are valid */
|
||||
char validJD; /* True (1) if iJD is valid */
|
||||
char validTZ; /* True (1) if tz is valid */
|
||||
char tzSet; /* Timezone was set explicitly */
|
||||
char isError; /* An overflow has occurred */
|
||||
};
|
||||
|
||||
|
||||
@ -232,6 +232,14 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Put the DateTime object into its error state.
|
||||
*/
|
||||
static void datetimeError(DateTime *p){
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->isError = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
|
||||
** that the YYYY-MM-DD is according to the Gregorian calendar.
|
||||
@ -251,6 +259,10 @@ static void computeJD(DateTime *p){
|
||||
M = 1;
|
||||
D = 1;
|
||||
}
|
||||
if( Y<-4713 || Y>9999 ){
|
||||
datetimeError(p);
|
||||
return;
|
||||
}
|
||||
if( M<=2 ){
|
||||
Y--;
|
||||
M += 12;
|
||||
@ -373,7 +385,7 @@ static int parseDateOrTime(
|
||||
** The input is the JulianDay times 86400000.
|
||||
*/
|
||||
static int validJulianDay(sqlite3_int64 iJD){
|
||||
return iJD>=148699540800000 && iJD<=464269060799999;
|
||||
return iJD>=0 && iJD<=464269060799999;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -387,8 +399,7 @@ static void computeYMD(DateTime *p){
|
||||
p->M = 1;
|
||||
p->D = 1;
|
||||
}else if( !validJulianDay(p->iJD) ){
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->isError = 1;
|
||||
datetimeError(p);
|
||||
return;
|
||||
}else{
|
||||
Z = (int)((p->iJD + 43200000)/86400000);
|
||||
@ -713,6 +724,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
|
||||
case '8':
|
||||
case '9': {
|
||||
double rRounder;
|
||||
double rAbs;
|
||||
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
|
||||
if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
|
||||
rc = 1;
|
||||
@ -749,15 +761,16 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
|
||||
computeJD(p);
|
||||
rc = 0;
|
||||
rRounder = r<0 ? -0.5 : +0.5;
|
||||
if( n==3 && strcmp(z,"day")==0 ){
|
||||
rAbs = r<0 ? -r : r;
|
||||
if( n==3 && strcmp(z,"day")==0 && rAbs<5373485.0 ){
|
||||
p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
|
||||
}else if( n==4 && strcmp(z,"hour")==0 ){
|
||||
}else if( n==4 && strcmp(z,"hour")==0 && rAbs<128963628.0 ){
|
||||
p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
|
||||
}else if( n==6 && strcmp(z,"minute")==0 ){
|
||||
}else if( n==6 && strcmp(z,"minute")==0 && rAbs<7737817680.0 ){
|
||||
p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
|
||||
}else if( n==6 && strcmp(z,"second")==0 ){
|
||||
}else if( n==6 && strcmp(z,"second")==0 && rAbs<464269060800.0 ){
|
||||
p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
|
||||
}else if( n==5 && strcmp(z,"month")==0 ){
|
||||
}else if( n==5 && strcmp(z,"month")==0 && rAbs<176546.0 ){
|
||||
int x, y;
|
||||
computeYMD_HMS(p);
|
||||
p->M += (int)r;
|
||||
@ -770,7 +783,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
|
||||
if( y!=r ){
|
||||
p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
|
||||
}
|
||||
}else if( n==4 && strcmp(z,"year")==0 ){
|
||||
}else if( n==4 && strcmp(z,"year")==0 && rAbs<14713.0 ){
|
||||
int y = (int)r;
|
||||
computeYMD_HMS(p);
|
||||
p->Y += y;
|
||||
|
@ -61,7 +61,7 @@ datetest 1.19 {julianday('2000-01-01 12:00:00.1')} 2451545.00000116
|
||||
datetest 1.20 {julianday('2000-01-01 12:00:00.01')} 2451545.00000012
|
||||
datetest 1.21 {julianday('2000-01-01 12:00:00.001')} 2451545.00000001
|
||||
datetest 1.22 {julianday('2000-01-01 12:00:00.')} NULL
|
||||
datetest 1.23 julianday(12345.6) NULL
|
||||
datetest 1.23 julianday(12345.6) 12345.6
|
||||
datetest 1.23b julianday(1721059.5) 1721059.5
|
||||
datetest 1.24 {julianday('2001-01-01 12:00:00 bogus')} NULL
|
||||
datetest 1.25 {julianday('2001-01-01 bogus')} NULL
|
||||
@ -418,6 +418,16 @@ datetest 8.19 {datetime('now','11.25 seconds')} {2003-10-22 12:34:11}
|
||||
datetest 8.90 {datetime('now','abcdefghijklmnopqrstuvwyxzABCDEFGHIJLMNOP')} NULL
|
||||
set sqlite_current_time 0
|
||||
|
||||
# Negative years work. Example: '-4713-11-26' is JD 1.5.
|
||||
#
|
||||
datetest 9.1 {julianday('-4713-11-24 12:00:00')} {0.0}
|
||||
datetest 9.2 {julianday(datetime(5))} {5.0}
|
||||
datetest 9.3 {julianday(datetime(10))} {10.0}
|
||||
datetest 9.4 {julianday(datetime(100))} {100.0}
|
||||
datetest 9.5 {julianday(datetime(1000))} {1000.0}
|
||||
datetest 9.6 {julianday(datetime(10000))} {10000.0}
|
||||
datetest 9.7 {julianday(datetime(100000))} {100000.0}
|
||||
|
||||
# datetime() with just an HH:MM:SS correctly inserts the date 2000-01-01.
|
||||
#
|
||||
datetest 10.1 {datetime('01:02:03')} {2000-01-01 01:02:03}
|
||||
@ -550,4 +560,41 @@ do_test date-15.2 {
|
||||
}
|
||||
} {1}
|
||||
|
||||
# Tests of extreme values in date/time functions. Run with UBSan or the
|
||||
# equivalent to verify no signed interger overflow warnings.
|
||||
#
|
||||
datetest 16.1 {date(147483649)} NULL
|
||||
datetest 16.2 {datetime(0)} {-4713-11-24 12:00:00}
|
||||
datetest 16.3 {datetime(5373484.49999999)} {9999-12-31 23:59:59}
|
||||
datetest 16.4 {julianday('-4713-11-24 12:00:00')} 0.0
|
||||
datetest 16.5 {julianday('9999-12-31 23:59:59.999')} 5373484.49999999
|
||||
datetest 16.6 {datetime(0,'+464269060799 seconds')} {9999-12-31 23:59:59}
|
||||
datetest 16.7 {datetime(0,'+464269060800 seconds')} NULL
|
||||
datetest 16.8 {datetime(0,'+7737817679 minutes')} {9999-12-31 23:59:00}
|
||||
datetest 16.9 {datetime(0,'+7737817680 minutes')} NULL
|
||||
datetest 16.10 {datetime(0,'+128963627 hours')} {9999-12-31 23:00:00}
|
||||
datetest 16.11 {datetime(0,'+128963628 hours')} NULL
|
||||
datetest 16.12 {datetime(0,'+5373484 days')} {9999-12-31 12:00:00}
|
||||
datetest 16.13 {datetime(0,'+5373485 days')} NULL
|
||||
datetest 16.14 {datetime(0,'+176545 months')} {9999-12-24 12:00:00}
|
||||
datetest 16.15 {datetime(0,'+176546 months')} NULL
|
||||
datetest 16.16 {datetime(0,'+14712 years')} {9999-11-24 12:00:00}
|
||||
datetest 16.17 {datetime(0,'+14713 years')} NULL
|
||||
datetest 16.20 {datetime(5373484.4999999,'-464269060799 seconds')} \
|
||||
{-4713-11-24 12:00:00}
|
||||
datetest 16.21 {datetime(5373484,'-464269060800 seconds')} NULL
|
||||
datetest 16.22 {datetime(5373484.4999999,'-7737817679 minutes')} \
|
||||
{-4713-11-24 12:00:59}
|
||||
datetest 16.23 {datetime(5373484,'-7737817680 minutes')} NULL
|
||||
datetest 16.24 {datetime(5373484.4999999,'-128963627 hours')} \
|
||||
{-4713-11-24 12:59:59}
|
||||
datetest 16.25 {datetime(5373484,'-128963628 hours')} NULL
|
||||
datetest 16.26 {datetime(5373484,'-5373484 days')} {-4713-11-24 12:00:00}
|
||||
datetest 16.27 {datetime(5373484,'-5373485 days')} NULL
|
||||
datetest 16.28 {datetime(5373484,'-176545 months')} {-4713-12-01 12:00:00}
|
||||
datetest 16.29 {datetime(5373484,'-176546 months')} NULL
|
||||
datetest 16.30 {datetime(5373484,'-14712 years')} {-4713-12-31 12:00:00}
|
||||
datetest 16.31 {datetime(5373484,'-14713 years')} NULL
|
||||
|
||||
|
||||
finish_test
|
||||
|
Loading…
x
Reference in New Issue
Block a user