From 0e20d90ab016b7ac926feba765f62d8b64017d50 Mon Sep 17 00:00:00 2001
From: Jeevan Ladhe <jeevan.ladhe@enterprisedb.com>
Date: Sun, 4 Aug 2019 09:08:20 +0530
Subject: [PATCH] Make have_error initialization more defensive v3

Basically get rid of the dependency to have caller
initalize the flag.
This patch addresses such occurrences in following functions:
pg_lsn_in_internal(), float8in_internal_opt_error(),
numeric_mod_opt_error(), numeric_div_opt_error() and
numeric_mod_opt_error().
Also, add have_error flag to macro RETURN_ERROR to make the
references more readable in float.c

Jeevan Ladhe
---
 src/backend/utils/adt/float.c         | 44 ++++++++++++++++++-----------------
 src/backend/utils/adt/jsonpath_exec.c |  6 ++---
 src/backend/utils/adt/numeric.c       |  9 +++++++
 src/backend/utils/adt/pg_lsn.c        |  5 +++-
 src/backend/utils/misc/guc.c          |  2 +-
 5 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 7540ca2..219a0bb 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -337,10 +337,10 @@ float8in(PG_FUNCTION_ARGS)
 }
 
 /* Convenience macro: set *have_error flag (if provided) or throw error */
-#define RETURN_ERROR(throw_error) \
+#define RETURN_ERROR(have_error, throw_error) \
 do { \
 	if (have_error) { \
-		*have_error = true; \
+		*(have_error) = true; \
 		return 0.0; \
 	} else { \
 		throw_error; \
@@ -376,6 +376,9 @@ float8in_internal_opt_error(char *num, char **endptr_p,
 	double		val;
 	char	   *endptr;
 
+	if (have_error)
+		*have_error = false;
+
 	/* skip leading whitespace */
 	while (*num != '\0' && isspace((unsigned char) *num))
 		num++;
@@ -385,10 +388,10 @@ float8in_internal_opt_error(char *num, char **endptr_p,
 	 * strtod() on different platforms.
 	 */
 	if (*num == '\0')
-		RETURN_ERROR(ereport(ERROR,
-							 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-							  errmsg("invalid input syntax for type %s: \"%s\"",
-									 type_name, orig_string))));
+		RETURN_ERROR(have_error, ereport(ERROR,
+								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+								 errmsg("invalid input syntax for type %s: \"%s\"",
+										type_name, orig_string))));
 
 	errno = 0;
 	val = strtod(num, &endptr);
@@ -461,19 +464,18 @@ float8in_internal_opt_error(char *num, char **endptr_p,
 				char	   *errnumber = pstrdup(num);
 
 				errnumber[endptr - num] = '\0';
-				RETURN_ERROR(ereport(ERROR,
-									 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-									  errmsg("\"%s\" is out of range for "
-											 "type double precision",
-											 errnumber))));
+				RETURN_ERROR(have_error, ereport(ERROR,
+								(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+								 errmsg("\"%s\" is out of range for type double precision",
+										errnumber))));
 			}
 		}
 		else
-			RETURN_ERROR(ereport(ERROR,
-								 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-								  errmsg("invalid input syntax for type "
-										 "%s: \"%s\"",
-										 type_name, orig_string))));
+			RETURN_ERROR(have_error, ereport(ERROR,
+								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+								 errmsg("invalid input syntax for type "
+										"%s: \"%s\"",
+										type_name, orig_string))));
 	}
 #ifdef HAVE_BUGGY_SOLARIS_STRTOD
 	else
@@ -496,11 +498,11 @@ float8in_internal_opt_error(char *num, char **endptr_p,
 	if (endptr_p)
 		*endptr_p = endptr;
 	else if (*endptr != '\0')
-		RETURN_ERROR(ereport(ERROR,
-							 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-							  errmsg("invalid input syntax for type "
-									 "%s: \"%s\"",
-									 type_name, orig_string))));
+		RETURN_ERROR(have_error, ereport(ERROR,
+								(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+								 errmsg("invalid input syntax for type "
+										"%s: \"%s\"",
+										type_name, orig_string))));
 
 	return val;
 }
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 293d6da..a0ead39 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -976,7 +976,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 				{
 					char	   *tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
 																		  NumericGetDatum(jb->val.numeric)));
-					bool		have_error = false;
+					bool		have_error;
 
 					(void) float8in_internal_opt_error(tmp,
 													   NULL,
@@ -997,7 +997,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 					double		val;
 					char	   *tmp = pnstrdup(jb->val.string.val,
 											   jb->val.string.len);
-					bool		have_error = false;
+					bool		have_error;
 
 					val = float8in_internal_opt_error(tmp,
 													  NULL,
@@ -1521,7 +1521,7 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
 	}
 	else
 	{
-		bool		error = false;
+		bool		error;
 
 		res = func(lval->val.numeric, rval->val.numeric, &error);
 
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 201784b..7b0874b 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -2605,6 +2605,9 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	Numeric		res;
 	int			rscale;
 
+	if(have_error)
+		*have_error = false;
+
 	/*
 	 * Handle NaN
 	 */
@@ -2721,6 +2724,9 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
 	NumericVar	arg2;
 	NumericVar	result;
 
+	if (have_error)
+		*have_error = false;
+
 	if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
 		return make_result(&const_nan);
 
@@ -6249,6 +6255,9 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
 	int			n;
 	Size		len;
 
+	if (have_error)
+		*have_error = false;
+
 	if (sign == NUMERIC_NAN)
 	{
 		result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);
diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c
index b4c6c23..90e9b8c 100644
--- a/src/backend/utils/adt/pg_lsn.c
+++ b/src/backend/utils/adt/pg_lsn.c
@@ -34,6 +34,9 @@ pg_lsn_in_internal(const char *str, bool *have_error)
 				off;
 	XLogRecPtr	result;
 
+	Assert(have_error != NULL);
+	*have_error = false;
+
 	/* Sanity check input format. */
 	len1 = strspn(str, "0123456789abcdefABCDEF");
 	if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
@@ -61,7 +64,7 @@ pg_lsn_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	XLogRecPtr	result;
-	bool		have_error = false;
+	bool		have_error;
 
 	result = pg_lsn_in_internal(str, &have_error);
 	if (have_error)
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index fc46360..ce179fc 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -11677,7 +11677,7 @@ check_recovery_target_lsn(char **newval, void **extra, GucSource source)
 	{
 		XLogRecPtr	lsn;
 		XLogRecPtr *myextra;
-		bool		have_error = false;
+		bool		have_error;
 
 		lsn = pg_lsn_in_internal(*newval, &have_error);
 		if (have_error)
-- 
2.7.4

