0002-Don-t-call-data-type-input-functions-in-GUC-check-ho.patch
text/plain
Filename: 0002-Don-t-call-data-type-input-functions-in-GUC-check-ho.patch
Type: text/plain
Part: 1
Patch
Format: format-patch
Series: patch 0002
Subject: Don't call data type input functions in GUC check hooks
| File | + | − |
|---|---|---|
| src/backend/utils/misc/guc.c | 53 | 50 |
From dc5011a7a798b1dfc5208bd41e83f002e708c7d1 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 12 Jun 2019 11:12:13 +0200
Subject: [PATCH 2/2] Don't call data type input functions in GUC check hooks
Instead of calling pg_lsn_in() in check_recovery_target_lsn and
timestamptz_in() in check_recovery_target_time, replicate the
respective code to some degree. The previous code tried to use
PG_TRY/PG_CATCH to handle errors in a way that is not safe, so now the
code contains no ereport() calls and can operate safely within the GUC
error handling system.
---
src/backend/utils/misc/guc.c | 103 ++++++++++++++++++-----------------
1 file changed, 53 insertions(+), 50 deletions(-)
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 1208eb9a68..3a52b4090b 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -86,7 +86,6 @@
#include "utils/float.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
-#include "utils/pg_lsn.h"
#include "utils/plancache.h"
#include "utils/portal.h"
#include "utils/ps_status.h"
@@ -11577,15 +11576,11 @@ check_recovery_target_time(char **newval, void **extra, GucSource source)
{
if (strcmp(*newval, "") != 0)
{
- TimestampTz time;
+ TimestampTz timestamp;
TimestampTz *myextra;
- MemoryContext oldcontext = CurrentMemoryContext;
/* reject some special values */
- if (strcmp(*newval, "epoch") == 0 ||
- strcmp(*newval, "infinity") == 0 ||
- strcmp(*newval, "-infinity") == 0 ||
- strcmp(*newval, "now") == 0 ||
+ if (strcmp(*newval, "now") == 0 ||
strcmp(*newval, "today") == 0 ||
strcmp(*newval, "tomorrow") == 0 ||
strcmp(*newval, "yesterday") == 0)
@@ -11593,31 +11588,40 @@ check_recovery_target_time(char **newval, void **extra, GucSource source)
return false;
}
- PG_TRY();
- {
- time = DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in,
- CStringGetDatum(*newval),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1)));
- }
- PG_CATCH();
+ /*
+ * parse timestamp value (see also timestamptz_in())
+ */
{
- ErrorData *edata;
-
- /* Save error info */
- MemoryContextSwitchTo(oldcontext);
- edata = CopyErrorData();
- FlushErrorState();
-
- /* Pass the error message */
- GUC_check_errdetail("%s", edata->message);
- FreeErrorData(edata);
- return false;
+ char *str = *newval;
+ fsec_t fsec;
+ struct pg_tm tt,
+ *tm = &tt;
+ int tz;
+ int dtype;
+ int nf;
+ int dterr;
+ char *field[MAXDATEFIELDS];
+ int ftype[MAXDATEFIELDS];
+ char workbuf[MAXDATELEN + MAXDATEFIELDS];
+
+ 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)
+ return false;
+ if (dtype != DTK_DATE)
+ return false;
+
+ if (tm2timestamp(tm, fsec, &tz, ×tamp) != 0)
+ {
+ GUC_check_errdetail("timestamp out of range: \"%s\"", str);
+ return false;
+ }
}
- PG_END_TRY();
myextra = (TimestampTz *) guc_malloc(ERROR, sizeof(TimestampTz));
- *myextra = time;
+ *myextra = timestamp;
*extra = (void *) myextra;
}
return true;
@@ -11668,6 +11672,8 @@ assign_recovery_target_name(const char *newval, void *extra)
recoveryTarget = RECOVERY_TARGET_UNSET;
}
+#define MAXPG_LSNCOMPONENT 8
+
static bool
check_recovery_target_lsn(char **newval, void **extra, GucSource source)
{
@@ -11675,33 +11681,30 @@ check_recovery_target_lsn(char **newval, void **extra, GucSource source)
{
XLogRecPtr lsn;
XLogRecPtr *myextra;
- MemoryContext oldcontext = CurrentMemoryContext;
/*
- * Convert the LSN string given by the user to XLogRecPtr form.
+ * Convert the LSN string given by the user to XLogRecPtr form (see
+ * also pg_lsn_in()).
*/
- PG_TRY();
- {
- lsn = DatumGetLSN(DirectFunctionCall3(pg_lsn_in,
- CStringGetDatum(*newval),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1)));
- }
- PG_CATCH();
{
- ErrorData *edata;
-
- /* Save error info */
- MemoryContextSwitchTo(oldcontext);
- edata = CopyErrorData();
- FlushErrorState();
-
- /* Pass the error message */
- GUC_check_errdetail("%s", edata->message);
- FreeErrorData(edata);
- return false;
+ char *str = *newval;
+ size_t len1;
+ size_t len2;
+ uint32 id;
+ uint32 off;
+
+ len1 = strspn(str, "0123456789abcdefABCDEF");
+ if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
+ return false;
+
+ len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
+ if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || str[len1 + 1 + len2] != '\0')
+ return false;
+
+ id = (uint32) strtoul(str, NULL, 16);
+ off = (uint32) strtoul(str + len1 + 1, NULL, 16);
+ lsn = ((uint64) id << 32) | off;
}
- PG_END_TRY();
myextra = (XLogRecPtr *) guc_malloc(ERROR, sizeof(XLogRecPtr));
*myextra = lsn;
--
2.22.0