Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b71310d

Browse files
author
Thomas G. Lockhart
committed
Add guard code to protect from buffer overruns on long date/time input
strings. Should go back in and look at doing this a bit more elegantly and (hopefully) cheaper. Probably not too bad anyway, but it seems a shame to scan the strings twice: once for length for this buffer overrun protection, and once to parse the line. Remove use of pow() in date/time handling; was already gone from everything *but* the time data types. Define macros for handling typmod manipulation for date/time types. Should be more robust than all of that brute-force inline code. Rename macros for masking and typmod manipulation to put TIMESTAMP_ or INTERVAL_ in front of the macro name, to reduce the possibility of name space collisions.
1 parent e025bb7 commit b71310d

File tree

6 files changed

+420
-322
lines changed

6 files changed

+420
-322
lines changed

src/backend/utils/adt/date.c

Lines changed: 80 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/date.c,v 1.69 2002/06/20 20:29:36 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.70 2002/08/04 06:44:47 thomas Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -57,6 +57,9 @@ date_in(PG_FUNCTION_ARGS)
5757
int ftype[MAXDATEFIELDS];
5858
char lowstr[MAXDATELEN + 1];
5959

60+
if (strlen(str) >= sizeof(lowstr))
61+
elog(ERROR, "Bad date external representation (too long) '%s'", str);
62+
6063
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
6164
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0))
6265
elog(ERROR, "Bad date external representation '%s'", str);
@@ -518,6 +521,9 @@ time_in(PG_FUNCTION_ARGS)
518521
int dtype;
519522
int ftype[MAXDATEFIELDS];
520523

524+
if (strlen(str) >= sizeof(lowstr))
525+
elog(ERROR, "Bad time external representation (too long) '%s'", str);
526+
521527
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
522528
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, NULL) != 0))
523529
elog(ERROR, "Bad time external representation '%s'", str);
@@ -606,37 +612,85 @@ time_scale(PG_FUNCTION_ARGS)
606612
PG_RETURN_TIMEADT(result);
607613
}
608614

615+
/* AdjustTimeForTypmod()
616+
* Force the precision of the time value to a specified value.
617+
* Uses *exactly* the same code as in AdjustTimestampForTypemod()
618+
* but we make a separate copy because those types do not
619+
* have a fundamental tie together but rather a coincidence of
620+
* implementation. - thomas
621+
*/
609622
static void
610623
AdjustTimeForTypmod(TimeADT *time, int32 typmod)
611624
{
612-
if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
613-
{
614625
#ifdef HAVE_INT64_TIMESTAMP
615-
static int64 TimeScale = INT64CONST(1000000);
626+
static const int64 TimeScales[MAX_TIMESTAMP_PRECISION+1] = {
627+
INT64CONST(1000000),
628+
INT64CONST(100000),
629+
INT64CONST(10000),
630+
INT64CONST(1000),
631+
INT64CONST(100),
632+
INT64CONST(10),
633+
INT64CONST(1)
634+
};
635+
636+
static const int64 TimeOffsets[MAX_TIMESTAMP_PRECISION+1] = {
637+
INT64CONST(-500000),
638+
INT64CONST(-50000),
639+
INT64CONST(-5000),
640+
INT64CONST(-500),
641+
INT64CONST(-50),
642+
INT64CONST(-5),
643+
INT64CONST(0)
644+
};
616645
#else
617-
static double TimeScale = 1;
646+
static const double TimeScales[MAX_TIMESTAMP_PRECISION+1] = {
647+
1,
648+
10,
649+
100,
650+
1000,
651+
10000,
652+
100000,
653+
1000000
654+
};
655+
656+
static const double TimeOffsets[MAX_TIMESTAMP_PRECISION+1] = {
657+
0.5,
658+
0.05,
659+
0.005,
660+
0.0005,
661+
0.00005,
662+
0.000005,
663+
0.0000005
664+
};
618665
#endif
619-
static int32 TimeTypmod = 0;
620666

621-
if (typmod != TimeTypmod)
622-
{
667+
if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
668+
{
623669
#ifdef HAVE_INT64_TIMESTAMP
624-
TimeScale = pow(10.0, (MAX_TIME_PRECISION-typmod));
625-
#else
626-
TimeScale = pow(10.0, typmod);
627-
#endif
628-
TimeTypmod = typmod;
670+
/* we have different truncation behavior depending on sign */
671+
if (*time >= INT64CONST(0))
672+
{
673+
*time = ((*time / TimeScales[typmod])
674+
* TimeScales[typmod]);
675+
}
676+
else
677+
{
678+
*time = (((*time + TimeOffsets[typmod]) / TimeScales[typmod])
679+
* TimeScales[typmod]);
629680
}
630-
631-
#ifdef HAVE_INT64_TIMESTAMP
632-
*time = ((*time / TimeScale) * TimeScale);
633-
if (*time >= INT64CONST(86400000000))
634-
*time -= INT64CONST(86400000000);
635681
#else
636-
*time = (rint(((double) *time) * TimeScale) / TimeScale);
637-
638-
if (*time >= 86400)
639-
*time -= 86400;
682+
/* we have different truncation behavior depending on sign */
683+
if (*time >= 0)
684+
{
685+
*time = (rint(((double) *time) * TimeScales[typmod])
686+
/ TimeScales[typmod]);
687+
}
688+
else
689+
{
690+
/* Scale and truncate first, then add to help the rounding behavior */
691+
*time = (rint((((double) *time) * TimeScales[typmod]) + TimeOffsets[typmod])
692+
/ TimeScales[typmod]);
693+
}
640694
#endif
641695
}
642696

@@ -1269,6 +1323,10 @@ timetz_in(PG_FUNCTION_ARGS)
12691323
int dtype;
12701324
int ftype[MAXDATEFIELDS];
12711325

1326+
if (strlen(str) >= sizeof(lowstr))
1327+
elog(ERROR, "Bad time with time zone"
1328+
" external representation (too long) '%s'", str);
1329+
12721330
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
12731331
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
12741332
elog(ERROR, "Bad time external representation '%s'", str);

0 commit comments

Comments
 (0)