summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/timestamp.c
diff options
context:
space:
mode:
authorNeil Conway <neilc@samurai.com>2005-05-26 02:04:14 +0000
committerNeil Conway <neilc@samurai.com>2005-05-26 02:04:14 +0000
commit63e0d612f5a53d76218d4e59a35287391e284561 (patch)
tree1acd1cc27ec9fd5855a6878f5f0d93f0683863e0 /src/backend/utils/adt/timestamp.c
parent15e4d1e2a7f565d805692daad895a07802279aea (diff)
Adjust datetime parsing to be more robust. We now pass the length of the
working buffer into ParseDateTime() and reject too-long input there, rather than checking the length of the input string before calling ParseDateTime(). The old method was bogus because ParseDateTime() can use a variable amount of working space, depending on the content of the input string (e.g. how many fields need to be NUL terminated). This fixes a minor stack overrun -- I don't _think_ it's exploitable, although I won't claim to be an expert. Along the way, fix a bug reported by Mark Dilger: the working buffer allocated by interval_in() was too short, which resulted in rejecting some perfectly valid interval input values. I added a regression test for this fix.
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r--src/backend/utils/adt/timestamp.c26
1 files changed, 10 insertions, 16 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 9aa28ffcc6a..27e0523f49c 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.123 2005/05/24 02:09:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.124 2005/05/26 02:04:13 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -77,12 +77,10 @@ timestamp_in(PG_FUNCTION_ARGS)
int dterr;
char *field[MAXDATEFIELDS];
int ftype[MAXDATEFIELDS];
- char lowstr[MAXDATELEN + MAXDATEFIELDS];
+ char workbuf[MAXDATELEN + MAXDATEFIELDS];
- if (strlen(str) >= sizeof(lowstr))
- dterr = DTERR_BAD_FORMAT;
- else
- dterr = ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf);
+ dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
+ field, ftype, MAXDATEFIELDS, &nf);
if (dterr == 0)
dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz);
if (dterr != 0)
@@ -317,12 +315,10 @@ timestamptz_in(PG_FUNCTION_ARGS)
int dterr;
char *field[MAXDATEFIELDS];
int ftype[MAXDATEFIELDS];
- char lowstr[MAXDATELEN + MAXDATEFIELDS];
+ char workbuf[MAXDATELEN + MAXDATEFIELDS];
- if (strlen(str) >= sizeof(lowstr))
- dterr = DTERR_BAD_FORMAT;
- else
- dterr = ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf);
+ dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
+ field, ftype, MAXDATEFIELDS, &nf);
if (dterr == 0)
dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz);
if (dterr != 0)
@@ -493,7 +489,7 @@ interval_in(PG_FUNCTION_ARGS)
int dterr;
char *field[MAXDATEFIELDS];
int ftype[MAXDATEFIELDS];
- char lowstr[MAXDATELEN + MAXDATEFIELDS];
+ char workbuf[256];
tm->tm_year = 0;
tm->tm_mon = 0;
@@ -503,10 +499,8 @@ interval_in(PG_FUNCTION_ARGS)
tm->tm_sec = 0;
fsec = 0;
- if (strlen(str) >= sizeof(lowstr))
- dterr = DTERR_BAD_FORMAT;
- else
- dterr = ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf);
+ dterr = ParseDateTime(str, workbuf, sizeof(workbuf), field,
+ ftype, MAXDATEFIELDS, &nf);
if (dterr == 0)
dterr = DecodeInterval(field, ftype, nf, &dtype, tm, &fsec);
if (dterr != 0)