@@ -983,7 +983,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
983
983
int fmask = 0 ,
984
984
tmask ,
985
985
type ;
986
- int ptype = 0 ; /* "prefix type" for ISO y2001m02d04 format */
986
+ int ptype = 0 ; /* "prefix type" for ISO and Julian formats */
987
987
int i ;
988
988
int val ;
989
989
int dterr ;
@@ -1071,6 +1071,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
1071
1071
{
1072
1072
char * cp ;
1073
1073
1074
+ /*
1075
+ * Allow a preceding "t" field, but no other units.
1076
+ */
1074
1077
if (ptype != 0 )
1075
1078
{
1076
1079
/* Sanity check; should not fail this test */
@@ -1175,8 +1178,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
1175
1178
case DTK_NUMBER :
1176
1179
1177
1180
/*
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
1180
1182
*/
1181
1183
if (ptype != 0 )
1182
1184
{
@@ -1187,85 +1189,11 @@ DecodeDateTime(char **field, int *ftype, int nf,
1187
1189
value = strtoint (field [i ], & cp , 10 );
1188
1190
if (errno == ERANGE )
1189
1191
return DTERR_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
- case DTK_JULIAN :
1199
- case DTK_TIME :
1200
- case DTK_SECOND :
1201
- break ;
1202
- default :
1203
- return DTERR_BAD_FORMAT ;
1204
- break ;
1205
- }
1206
- else if (* cp != '\0' )
1192
+ if (* cp != '.' && * cp != '\0' )
1207
1193
return DTERR_BAD_FORMAT ;
1208
1194
1209
1195
switch (ptype )
1210
1196
{
1211
- case DTK_YEAR :
1212
- tm -> tm_year = value ;
1213
- tmask = DTK_M (YEAR );
1214
- break ;
1215
-
1216
- case DTK_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
- case DTK_DAY :
1236
- tm -> tm_mday = value ;
1237
- tmask = DTK_M (DAY );
1238
- break ;
1239
-
1240
- case DTK_HOUR :
1241
- tm -> tm_hour = value ;
1242
- tmask = DTK_M (HOUR );
1243
- break ;
1244
-
1245
- case DTK_MINUTE :
1246
- tm -> tm_min = value ;
1247
- tmask = DTK_M (MINUTE );
1248
- break ;
1249
-
1250
- case DTK_SECOND :
1251
- tm -> tm_sec = value ;
1252
- tmask = DTK_M (SECOND );
1253
- if (* cp == '.' )
1254
- {
1255
- dterr = ParseFractionalSecond (cp , fsec );
1256
- if (dterr )
1257
- return dterr ;
1258
- tmask = DTK_ALL_SECS_M ;
1259
- }
1260
- break ;
1261
-
1262
- case DTK_TZ :
1263
- tmask = DTK_M (TZ );
1264
- dterr = DecodeTimezone (field [i ], tzp );
1265
- if (dterr )
1266
- return dterr ;
1267
- break ;
1268
-
1269
1197
case DTK_JULIAN :
1270
1198
/* previous field was a label for "julian date" */
1271
1199
if (value < 0 )
@@ -1519,6 +1447,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
1519
1447
1520
1448
case UNITS :
1521
1449
tmask = 0 ;
1450
+ /* reject consecutive unhandled units */
1451
+ if (ptype != 0 )
1452
+ return DTERR_BAD_FORMAT ;
1522
1453
ptype = val ;
1523
1454
break ;
1524
1455
@@ -1534,18 +1465,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
1534
1465
if ((fmask & DTK_DATE_M ) != DTK_DATE_M )
1535
1466
return DTERR_BAD_FORMAT ;
1536
1467
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 )
1547
1470
return DTERR_BAD_FORMAT ;
1548
-
1549
1471
ptype = val ;
1550
1472
break ;
1551
1473
@@ -1576,6 +1498,10 @@ DecodeDateTime(char **field, int *ftype, int nf,
1576
1498
fmask |= tmask ;
1577
1499
} /* end loop over fields */
1578
1500
1501
+ /* reject if prefix type appeared and was never handled */
1502
+ if (ptype != 0 )
1503
+ return DTERR_BAD_FORMAT ;
1504
+
1579
1505
/* do additional checking for normal date specs (but not "infinity" etc) */
1580
1506
if (* dtype == DTK_DATE )
1581
1507
{
@@ -1943,7 +1869,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
1943
1869
int fmask = 0 ,
1944
1870
tmask ,
1945
1871
type ;
1946
- int ptype = 0 ; /* "prefix type" for ISO h04mm05s06 format */
1872
+ int ptype = 0 ; /* "prefix type" for ISO and Julian formats */
1947
1873
int i ;
1948
1874
int val ;
1949
1875
int dterr ;
@@ -2070,112 +1996,26 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
2070
1996
case DTK_NUMBER :
2071
1997
2072
1998
/*
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
2075
2000
*/
2076
2001
if (ptype != 0 )
2077
2002
{
2078
2003
char * cp ;
2079
2004
int value ;
2080
2005
2081
- /* Only accept a date under limited circumstances */
2082
- switch (ptype )
2083
- {
2084
- case DTK_JULIAN :
2085
- case DTK_YEAR :
2086
- case DTK_MONTH :
2087
- case DTK_DAY :
2088
- if (tzp == NULL )
2089
- return DTERR_BAD_FORMAT ;
2090
- default :
2091
- break ;
2092
- }
2093
-
2094
2006
errno = 0 ;
2095
2007
value = strtoint (field [i ], & cp , 10 );
2096
2008
if (errno == ERANGE )
2097
2009
return DTERR_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
- case DTK_JULIAN :
2107
- case DTK_TIME :
2108
- case DTK_SECOND :
2109
- break ;
2110
- default :
2111
- return DTERR_BAD_FORMAT ;
2112
- break ;
2113
- }
2114
- else if (* cp != '\0' )
2010
+ if (* cp != '.' && * cp != '\0' )
2115
2011
return DTERR_BAD_FORMAT ;
2116
2012
2117
2013
switch (ptype )
2118
2014
{
2119
- case DTK_YEAR :
2120
- tm -> tm_year = value ;
2121
- tmask = DTK_M (YEAR );
2122
- break ;
2123
-
2124
- case DTK_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
- case DTK_DAY :
2144
- tm -> tm_mday = value ;
2145
- tmask = DTK_M (DAY );
2146
- break ;
2147
-
2148
- case DTK_HOUR :
2149
- tm -> tm_hour = value ;
2150
- tmask = DTK_M (HOUR );
2151
- break ;
2152
-
2153
- case DTK_MINUTE :
2154
- tm -> tm_min = value ;
2155
- tmask = DTK_M (MINUTE );
2156
- break ;
2157
-
2158
- case DTK_SECOND :
2159
- tm -> tm_sec = value ;
2160
- tmask = DTK_M (SECOND );
2161
- if (* cp == '.' )
2162
- {
2163
- dterr = ParseFractionalSecond (cp , fsec );
2164
- if (dterr )
2165
- return dterr ;
2166
- tmask = DTK_ALL_SECS_M ;
2167
- }
2168
- break ;
2169
-
2170
- case DTK_TZ :
2171
- tmask = DTK_M (TZ );
2172
- dterr = DecodeTimezone (field [i ], tzp );
2173
- if (dterr )
2174
- return dterr ;
2175
- break ;
2176
-
2177
2015
case DTK_JULIAN :
2178
2016
/* previous field was a label for "julian date" */
2017
+ if (tzp == NULL )
2018
+ return DTERR_BAD_FORMAT ;
2179
2019
if (value < 0 )
2180
2020
return DTERR_FIELD_OVERFLOW ;
2181
2021
tmask = DTK_DATE_M ;
@@ -2378,24 +2218,17 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
2378
2218
2379
2219
case UNITS :
2380
2220
tmask = 0 ;
2221
+ /* reject consecutive unhandled units */
2222
+ if (ptype != 0 )
2223
+ return DTERR_BAD_FORMAT ;
2381
2224
ptype = val ;
2382
2225
break ;
2383
2226
2384
2227
case ISOTIME :
2385
2228
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 )
2397
2231
return DTERR_BAD_FORMAT ;
2398
-
2399
2232
ptype = val ;
2400
2233
break ;
2401
2234
@@ -2426,6 +2259,10 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
2426
2259
fmask |= tmask ;
2427
2260
} /* end loop over fields */
2428
2261
2262
+ /* reject if prefix type appeared and was never handled */
2263
+ if (ptype != 0 )
2264
+ return DTERR_BAD_FORMAT ;
2265
+
2429
2266
/* do final checking/adjustment of Y/M/D fields */
2430
2267
dterr = ValidateDate (fmask , isjulian , is2digits , bc , tm );
2431
2268
if (dterr )
0 commit comments