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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy