Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 630684d

Browse files
committed
Improve documentation of ParseDateTime(). Reorder tests to prevent
writing one more value into return arrays than will fit. This is potentially a stack smash, though I do not think it is a problem in current uses of the routine, since a failure return causes elog anyway.
1 parent 9d41073 commit 630684d

File tree

2 files changed

+39
-24
lines changed

2 files changed

+39
-24
lines changed

src/backend/utils/adt/datetime.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.111 2003/08/05 17:39:19 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.112 2003/08/05 18:30:21 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -699,30 +699,54 @@ TrimTrailingZeros(char *str)
699699

700700

701701
/* ParseDateTime()
702-
* Break string into tokens based on a date/time context.
702+
* Break string into tokens based on a date/time context.
703+
* Returns 0 if successful, -1 if bogus input detected.
704+
*
705+
* timestr - the input string
706+
* lowstr - workspace for field string storage (must be large enough for
707+
* a copy of the input string, including trailing null)
708+
* field[] - pointers to field strings are returned in this array
709+
* ftype[] - field type indicators are returned in this array
710+
* maxfields - dimensions of the above two arrays
711+
* *numfields - set to the actual number of fields detected
712+
*
713+
* The fields extracted from the input are stored as separate, null-terminated
714+
* strings in the workspace at lowstr. Any text is converted to lower case.
715+
*
703716
* Several field types are assigned:
704717
* DTK_NUMBER - digits and (possibly) a decimal point
705718
* DTK_DATE - digits and two delimiters, or digits and text
706719
* DTK_TIME - digits, colon delimiters, and possibly a decimal point
707720
* DTK_STRING - text (no digits)
708721
* DTK_SPECIAL - leading "+" or "-" followed by text
709722
* DTK_TZ - leading "+" or "-" followed by digits
723+
*
710724
* Note that some field types can hold unexpected items:
711725
* DTK_NUMBER can hold date fields (yy.ddd)
712726
* DTK_STRING can hold months (January) and time zones (PST)
713727
* DTK_DATE can hold Posix time zones (GMT-8)
714728
*/
715729
int
716-
ParseDateTime(char *timestr, char *lowstr,
730+
ParseDateTime(const char *timestr, char *lowstr,
717731
char **field, int *ftype, int maxfields, int *numfields)
718732
{
719733
int nf = 0;
720-
char *cp = timestr;
734+
const char *cp = timestr;
721735
char *lp = lowstr;
722736

723737
/* outer loop through fields */
724738
while (*cp != '\0')
725739
{
740+
/* Ignore spaces between fields */
741+
if (isspace((unsigned char) *cp))
742+
{
743+
cp++;
744+
continue;
745+
}
746+
747+
/* Record start of current field */
748+
if (nf >= maxfields)
749+
return -1;
726750
field[nf] = lp;
727751

728752
/* leading digit? then date or time */
@@ -745,32 +769,32 @@ ParseDateTime(char *timestr, char *lowstr,
745769
else if ((*cp == '-') || (*cp == '/') || (*cp == '.'))
746770
{
747771
/* save delimiting character to use later */
748-
char *dp = cp;
772+
char delim = *cp;
749773

750774
*lp++ = *cp++;
751775
/* second field is all digits? then no embedded text month */
752776
if (isdigit((unsigned char) *cp))
753777
{
754-
ftype[nf] = ((*dp == '.') ? DTK_NUMBER : DTK_DATE);
778+
ftype[nf] = ((delim == '.') ? DTK_NUMBER : DTK_DATE);
755779
while (isdigit((unsigned char) *cp))
756780
*lp++ = *cp++;
757781

758782
/*
759783
* insist that the delimiters match to get a
760784
* three-field date.
761785
*/
762-
if (*cp == *dp)
786+
if (*cp == delim)
763787
{
764788
ftype[nf] = DTK_DATE;
765789
*lp++ = *cp++;
766-
while (isdigit((unsigned char) *cp) || (*cp == *dp))
790+
while (isdigit((unsigned char) *cp) || (*cp == delim))
767791
*lp++ = *cp++;
768792
}
769793
}
770794
else
771795
{
772796
ftype[nf] = DTK_DATE;
773-
while (isalnum((unsigned char) *cp) || (*cp == *dp))
797+
while (isalnum((unsigned char) *cp) || (*cp == delim))
774798
*lp++ = tolower((unsigned char) *cp++);
775799
}
776800
}
@@ -809,20 +833,14 @@ ParseDateTime(char *timestr, char *lowstr,
809833
*/
810834
if ((*cp == '-') || (*cp == '/') || (*cp == '.'))
811835
{
812-
char *dp = cp;
836+
char delim = *cp;
813837

814838
ftype[nf] = DTK_DATE;
815839
*lp++ = *cp++;
816-
while (isdigit((unsigned char) *cp) || (*cp == *dp))
840+
while (isdigit((unsigned char) *cp) || (*cp == delim))
817841
*lp++ = *cp++;
818842
}
819843
}
820-
/* skip leading spaces */
821-
else if (isspace((unsigned char) *cp))
822-
{
823-
cp++;
824-
continue;
825-
}
826844
/* sign? then special or numeric timezone */
827845
else if ((*cp == '+') || (*cp == '-'))
828846
{
@@ -851,12 +869,11 @@ ParseDateTime(char *timestr, char *lowstr,
851869
else
852870
return -1;
853871
}
854-
/* ignore punctuation but use as delimiter */
872+
/* ignore other punctuation but use as delimiter */
855873
else if (ispunct((unsigned char) *cp))
856874
{
857875
cp++;
858876
continue;
859-
860877
}
861878
/* otherwise, something is not right... */
862879
else
@@ -865,14 +882,12 @@ ParseDateTime(char *timestr, char *lowstr,
865882
/* force in a delimiter after each field */
866883
*lp++ = '\0';
867884
nf++;
868-
if (nf > MAXDATEFIELDS)
869-
return -1;
870885
}
871886

872887
*numfields = nf;
873888

874889
return 0;
875-
} /* ParseDateTime() */
890+
}
876891

877892

878893
/* DecodeDateTime()

src/include/utils/datetime.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
12-
* $Id: datetime.h,v 1.43 2003/08/04 02:40:15 momjian Exp $
12+
* $Id: datetime.h,v 1.44 2003/08/05 18:30:21 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -277,7 +277,7 @@ extern void GetCurrentTimeUsec(struct tm * tm, fsec_t *fsec, int *tzp);
277277
extern void j2date(int jd, int *year, int *month, int *day);
278278
extern int date2j(int year, int month, int day);
279279

280-
extern int ParseDateTime(char *timestr, char *lowstr,
280+
extern int ParseDateTime(const char *timestr, char *lowstr,
281281
char **field, int *ftype,
282282
int maxfields, int *numfields);
283283
extern int DecodeDateTime(char **field, int *ftype,

0 commit comments

Comments
 (0)