Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5b3c595

Browse files
committed
Tighten error checks in datetime input, and remove bogus "ISO" format.
DecodeDateTime and DecodeTimeOnly had support for date input in thestyle "Y2023M03D16", which the comments claimed to be an "ISO" format.However, so far as I can find there is no such format in ISO 8601;they write units before numbers in intervals, but not in datetimes.Furthermore, the lesser-known ISO 8601-2 spec actually defines anincompatible format "2023Y03M16D". None of our documentation mentionssuch a format either. So let's just drop it.That leaves us with only two cases for a prefix unit specifier indatetimes: Julian dates written as Jnnnn, and the "T" separatordefined by ISO 8601. Add checks to catch misuse of these specifiers,that is consecutive specifiers or a dangling specifier at the end ofthe string. We do not however disallow a specifier that is separatedfrom the field that it disambiguates (by noise words or unrelatedfields). That being the case, remove some overly-aggressive errorchecks from the ISOTIME cases.Joseph Koshakow, editorialized a bit by me; thanks also toPeter Eisentraut for some standards-reading.Discussion:https://postgr.es/m/CAAvxfHf2Q1gKLiHGnuPOiyf0ASvKUM4BnMfsXuwgtYEb_Gx0Zw@mail.gmail.com
1 parent2b7259f commit5b3c595

File tree

3 files changed

+92
-220
lines changed

3 files changed

+92
-220
lines changed

‎src/backend/utils/adt/datetime.c‎

Lines changed: 29 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
983983
intfmask=0,
984984
tmask,
985985
type;
986-
intptype=0;/* "prefix type" for ISOy2001m02d04 format */
986+
intptype=0;/* "prefix type" for ISOand Julian formats */
987987
inti;
988988
intval;
989989
intdterr;
@@ -1071,6 +1071,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
10711071
{
10721072
char*cp;
10731073

1074+
/*
1075+
* Allow a preceding "t" field, but no other units.
1076+
*/
10741077
if (ptype!=0)
10751078
{
10761079
/* Sanity check; should not fail this test */
@@ -1175,8 +1178,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
11751178
caseDTK_NUMBER:
11761179

11771180
/*
1178-
* Was this an "ISO date" with embedded field labels? An
1179-
* example is "y2001m02d04" - thomas 2001-02-04
1181+
* Deal with cases where previous field labeled this one
11801182
*/
11811183
if (ptype!=0)
11821184
{
@@ -1187,85 +1189,11 @@ DecodeDateTime(char **field, int *ftype, int nf,
11871189
value=strtoint(field[i],&cp,10);
11881190
if (errno==ERANGE)
11891191
returnDTERR_FIELD_OVERFLOW;
1190-
1191-
/*
1192-
* only a few kinds are allowed to have an embedded
1193-
* decimal
1194-
*/
1195-
if (*cp=='.')
1196-
switch (ptype)
1197-
{
1198-
caseDTK_JULIAN:
1199-
caseDTK_TIME:
1200-
caseDTK_SECOND:
1201-
break;
1202-
default:
1203-
returnDTERR_BAD_FORMAT;
1204-
break;
1205-
}
1206-
elseif (*cp!='\0')
1192+
if (*cp!='.'&&*cp!='\0')
12071193
returnDTERR_BAD_FORMAT;
12081194

12091195
switch (ptype)
12101196
{
1211-
caseDTK_YEAR:
1212-
tm->tm_year=value;
1213-
tmask=DTK_M(YEAR);
1214-
break;
1215-
1216-
caseDTK_MONTH:
1217-
1218-
/*
1219-
* already have a month and hour? then assume
1220-
* minutes
1221-
*/
1222-
if ((fmask&DTK_M(MONTH))!=0&&
1223-
(fmask&DTK_M(HOUR))!=0)
1224-
{
1225-
tm->tm_min=value;
1226-
tmask=DTK_M(MINUTE);
1227-
}
1228-
else
1229-
{
1230-
tm->tm_mon=value;
1231-
tmask=DTK_M(MONTH);
1232-
}
1233-
break;
1234-
1235-
caseDTK_DAY:
1236-
tm->tm_mday=value;
1237-
tmask=DTK_M(DAY);
1238-
break;
1239-
1240-
caseDTK_HOUR:
1241-
tm->tm_hour=value;
1242-
tmask=DTK_M(HOUR);
1243-
break;
1244-
1245-
caseDTK_MINUTE:
1246-
tm->tm_min=value;
1247-
tmask=DTK_M(MINUTE);
1248-
break;
1249-
1250-
caseDTK_SECOND:
1251-
tm->tm_sec=value;
1252-
tmask=DTK_M(SECOND);
1253-
if (*cp=='.')
1254-
{
1255-
dterr=ParseFractionalSecond(cp,fsec);
1256-
if (dterr)
1257-
returndterr;
1258-
tmask=DTK_ALL_SECS_M;
1259-
}
1260-
break;
1261-
1262-
caseDTK_TZ:
1263-
tmask=DTK_M(TZ);
1264-
dterr=DecodeTimezone(field[i],tzp);
1265-
if (dterr)
1266-
returndterr;
1267-
break;
1268-
12691197
caseDTK_JULIAN:
12701198
/* previous field was a label for "julian date" */
12711199
if (value<0)
@@ -1519,6 +1447,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
15191447

15201448
caseUNITS:
15211449
tmask=0;
1450+
/* reject consecutive unhandled units */
1451+
if (ptype!=0)
1452+
returnDTERR_BAD_FORMAT;
15221453
ptype=val;
15231454
break;
15241455

@@ -1534,18 +1465,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
15341465
if ((fmask&DTK_DATE_M)!=DTK_DATE_M)
15351466
returnDTERR_BAD_FORMAT;
15361467

1537-
/***
1538-
* We will need one of the following fields:
1539-
*DTK_NUMBER should be hhmmss.fff
1540-
*DTK_TIME should be hh:mm:ss.fff
1541-
*DTK_DATE should be hhmmss-zz
1542-
***/
1543-
if (i >=nf-1||
1544-
(ftype[i+1]!=DTK_NUMBER&&
1545-
ftype[i+1]!=DTK_TIME&&
1546-
ftype[i+1]!=DTK_DATE))
1468+
/* reject consecutive unhandled units */
1469+
if (ptype!=0)
15471470
returnDTERR_BAD_FORMAT;
1548-
15491471
ptype=val;
15501472
break;
15511473

@@ -1576,6 +1498,10 @@ DecodeDateTime(char **field, int *ftype, int nf,
15761498
fmask |=tmask;
15771499
}/* end loop over fields */
15781500

1501+
/* reject if prefix type appeared and was never handled */
1502+
if (ptype!=0)
1503+
returnDTERR_BAD_FORMAT;
1504+
15791505
/* do additional checking for normal date specs (but not "infinity" etc) */
15801506
if (*dtype==DTK_DATE)
15811507
{
@@ -1943,7 +1869,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
19431869
intfmask=0,
19441870
tmask,
19451871
type;
1946-
intptype=0;/* "prefix type" for ISOh04mm05s06 format */
1872+
intptype=0;/* "prefix type" for ISOand Julian formats */
19471873
inti;
19481874
intval;
19491875
intdterr;
@@ -2070,112 +1996,26 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
20701996
caseDTK_NUMBER:
20711997

20721998
/*
2073-
* Was this an "ISO time" with embedded field labels? An
2074-
* example is "h04mm05s06" - thomas 2001-02-04
1999+
* Deal with cases where previous field labeled this one
20752000
*/
20762001
if (ptype!=0)
20772002
{
20782003
char*cp;
20792004
intvalue;
20802005

2081-
/* Only accept a date under limited circumstances */
2082-
switch (ptype)
2083-
{
2084-
caseDTK_JULIAN:
2085-
caseDTK_YEAR:
2086-
caseDTK_MONTH:
2087-
caseDTK_DAY:
2088-
if (tzp==NULL)
2089-
returnDTERR_BAD_FORMAT;
2090-
default:
2091-
break;
2092-
}
2093-
20942006
errno=0;
20952007
value=strtoint(field[i],&cp,10);
20962008
if (errno==ERANGE)
20972009
returnDTERR_FIELD_OVERFLOW;
2098-
2099-
/*
2100-
* only a few kinds are allowed to have an embedded
2101-
* decimal
2102-
*/
2103-
if (*cp=='.')
2104-
switch (ptype)
2105-
{
2106-
caseDTK_JULIAN:
2107-
caseDTK_TIME:
2108-
caseDTK_SECOND:
2109-
break;
2110-
default:
2111-
returnDTERR_BAD_FORMAT;
2112-
break;
2113-
}
2114-
elseif (*cp!='\0')
2010+
if (*cp!='.'&&*cp!='\0')
21152011
returnDTERR_BAD_FORMAT;
21162012

21172013
switch (ptype)
21182014
{
2119-
caseDTK_YEAR:
2120-
tm->tm_year=value;
2121-
tmask=DTK_M(YEAR);
2122-
break;
2123-
2124-
caseDTK_MONTH:
2125-
2126-
/*
2127-
* already have a month and hour? then assume
2128-
* minutes
2129-
*/
2130-
if ((fmask&DTK_M(MONTH))!=0&&
2131-
(fmask&DTK_M(HOUR))!=0)
2132-
{
2133-
tm->tm_min=value;
2134-
tmask=DTK_M(MINUTE);
2135-
}
2136-
else
2137-
{
2138-
tm->tm_mon=value;
2139-
tmask=DTK_M(MONTH);
2140-
}
2141-
break;
2142-
2143-
caseDTK_DAY:
2144-
tm->tm_mday=value;
2145-
tmask=DTK_M(DAY);
2146-
break;
2147-
2148-
caseDTK_HOUR:
2149-
tm->tm_hour=value;
2150-
tmask=DTK_M(HOUR);
2151-
break;
2152-
2153-
caseDTK_MINUTE:
2154-
tm->tm_min=value;
2155-
tmask=DTK_M(MINUTE);
2156-
break;
2157-
2158-
caseDTK_SECOND:
2159-
tm->tm_sec=value;
2160-
tmask=DTK_M(SECOND);
2161-
if (*cp=='.')
2162-
{
2163-
dterr=ParseFractionalSecond(cp,fsec);
2164-
if (dterr)
2165-
returndterr;
2166-
tmask=DTK_ALL_SECS_M;
2167-
}
2168-
break;
2169-
2170-
caseDTK_TZ:
2171-
tmask=DTK_M(TZ);
2172-
dterr=DecodeTimezone(field[i],tzp);
2173-
if (dterr)
2174-
returndterr;
2175-
break;
2176-
21772015
caseDTK_JULIAN:
21782016
/* previous field was a label for "julian date" */
2017+
if (tzp==NULL)
2018+
returnDTERR_BAD_FORMAT;
21792019
if (value<0)
21802020
returnDTERR_FIELD_OVERFLOW;
21812021
tmask=DTK_DATE_M;
@@ -2378,24 +2218,17 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
23782218

23792219
caseUNITS:
23802220
tmask=0;
2221+
/* reject consecutive unhandled units */
2222+
if (ptype!=0)
2223+
returnDTERR_BAD_FORMAT;
23812224
ptype=val;
23822225
break;
23832226

23842227
caseISOTIME:
23852228
tmask=0;
2386-
2387-
/***
2388-
* We will need one of the following fields:
2389-
*DTK_NUMBER should be hhmmss.fff
2390-
*DTK_TIME should be hh:mm:ss.fff
2391-
*DTK_DATE should be hhmmss-zz
2392-
***/
2393-
if (i >=nf-1||
2394-
(ftype[i+1]!=DTK_NUMBER&&
2395-
ftype[i+1]!=DTK_TIME&&
2396-
ftype[i+1]!=DTK_DATE))
2229+
/* reject consecutive unhandled units */
2230+
if (ptype!=0)
23972231
returnDTERR_BAD_FORMAT;
2398-
23992232
ptype=val;
24002233
break;
24012234

@@ -2426,6 +2259,10 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
24262259
fmask |=tmask;
24272260
}/* end loop over fields */
24282261

2262+
/* reject if prefix type appeared and was never handled */
2263+
if (ptype!=0)
2264+
returnDTERR_BAD_FORMAT;
2265+
24292266
/* do final checking/adjustment of Y/M/D fields */
24302267
dterr=ValidateDate(fmask,isjulian,is2digits,bc,tm);
24312268
if (dterr)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp