1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-21 10:42:50 +03:00

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.
This commit is contained in:
Thomas G. Lockhart
2002-08-04 06:44:47 +00:00
parent e025bb7a72
commit b71310d8e0
6 changed files with 418 additions and 320 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.69 2002/06/20 20:29:36 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.70 2002/08/04 06:44:47 thomas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -57,6 +57,9 @@ date_in(PG_FUNCTION_ARGS)
int ftype[MAXDATEFIELDS];
char lowstr[MAXDATELEN + 1];
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad date external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0))
elog(ERROR, "Bad date external representation '%s'", str);
@@ -518,6 +521,9 @@ time_in(PG_FUNCTION_ARGS)
int dtype;
int ftype[MAXDATEFIELDS];
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad time external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, NULL) != 0))
elog(ERROR, "Bad time external representation '%s'", str);
@@ -606,37 +612,85 @@ time_scale(PG_FUNCTION_ARGS)
PG_RETURN_TIMEADT(result);
}
/* AdjustTimeForTypmod()
* Force the precision of the time value to a specified value.
* Uses *exactly* the same code as in AdjustTimestampForTypemod()
* but we make a separate copy because those types do not
* have a fundamental tie together but rather a coincidence of
* implementation. - thomas
*/
static void
AdjustTimeForTypmod(TimeADT *time, int32 typmod)
{
#ifdef HAVE_INT64_TIMESTAMP
static const int64 TimeScales[MAX_TIMESTAMP_PRECISION+1] = {
INT64CONST(1000000),
INT64CONST(100000),
INT64CONST(10000),
INT64CONST(1000),
INT64CONST(100),
INT64CONST(10),
INT64CONST(1)
};
static const int64 TimeOffsets[MAX_TIMESTAMP_PRECISION+1] = {
INT64CONST(-500000),
INT64CONST(-50000),
INT64CONST(-5000),
INT64CONST(-500),
INT64CONST(-50),
INT64CONST(-5),
INT64CONST(0)
};
#else
static const double TimeScales[MAX_TIMESTAMP_PRECISION+1] = {
1,
10,
100,
1000,
10000,
100000,
1000000
};
static const double TimeOffsets[MAX_TIMESTAMP_PRECISION+1] = {
0.5,
0.05,
0.005,
0.0005,
0.00005,
0.000005,
0.0000005
};
#endif
if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
{
#ifdef HAVE_INT64_TIMESTAMP
static int64 TimeScale = INT64CONST(1000000);
#else
static double TimeScale = 1;
#endif
static int32 TimeTypmod = 0;
if (typmod != TimeTypmod)
/* we have different truncation behavior depending on sign */
if (*time >= INT64CONST(0))
{
#ifdef HAVE_INT64_TIMESTAMP
TimeScale = pow(10.0, (MAX_TIME_PRECISION-typmod));
#else
TimeScale = pow(10.0, typmod);
#endif
TimeTypmod = typmod;
*time = ((*time / TimeScales[typmod])
* TimeScales[typmod]);
}
else
{
*time = (((*time + TimeOffsets[typmod]) / TimeScales[typmod])
* TimeScales[typmod]);
}
#ifdef HAVE_INT64_TIMESTAMP
*time = ((*time / TimeScale) * TimeScale);
if (*time >= INT64CONST(86400000000))
*time -= INT64CONST(86400000000);
#else
*time = (rint(((double) *time) * TimeScale) / TimeScale);
if (*time >= 86400)
*time -= 86400;
/* we have different truncation behavior depending on sign */
if (*time >= 0)
{
*time = (rint(((double) *time) * TimeScales[typmod])
/ TimeScales[typmod]);
}
else
{
/* Scale and truncate first, then add to help the rounding behavior */
*time = (rint((((double) *time) * TimeScales[typmod]) + TimeOffsets[typmod])
/ TimeScales[typmod]);
}
#endif
}
@@ -1269,6 +1323,10 @@ timetz_in(PG_FUNCTION_ARGS)
int dtype;
int ftype[MAXDATEFIELDS];
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad time with time zone"
" external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
elog(ERROR, "Bad time external representation '%s'", str);