From 9f4179494ef4612eadd8c2c6787391d85347fa4d Mon Sep 17 00:00:00 2001 From: Nikita Glukhov Date: Tue, 30 Aug 2022 00:13:36 +0300 Subject: [PATCH v9 3/9] Add safe input function for float4 --- src/backend/utils/adt/float.c | 70 +++++++++++++++++++---------------- src/include/utils/float.h | 1 + 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index fc8f39a7a98..d9da8c8466d 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -73,6 +73,16 @@ static double sind_q1(double x); static double cosd_q1(double x); static void init_degree_constants(void); +/* Convenience macro: set *have_error flag (if provided) or throw error */ +#define RETURN_ERROR(throw_error, have_error) \ +do { \ + if (have_error) { \ + *have_error = true; \ + return 0.0; \ + } else { \ + throw_error; \ + } \ +} while (0) /* * We use these out-of-line ereport() calls to report float overflow, @@ -159,10 +169,9 @@ is_infinite(double val) * result of 0xAE43FEp-107. * */ -Datum -float4in(PG_FUNCTION_ARGS) +float +float4in_opt_error(char *num, bool *have_error) { - char *num = PG_GETARG_CSTRING(0); char *orig_num; float val; char *endptr; @@ -183,10 +192,11 @@ float4in(PG_FUNCTION_ARGS) * strtod() on different platforms. */ if (*num == '\0') - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s: \"%s\"", - "real", orig_num))); + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s: \"%s\"", + "real", orig_num))), + have_error); errno = 0; val = strtof(num, &endptr); @@ -257,16 +267,18 @@ float4in(PG_FUNCTION_ARGS) (val >= HUGE_VALF || val <= -HUGE_VALF) #endif ) - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("\"%s\" is out of range for type real", - orig_num))); + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("\"%s\" is out of range for type real", + orig_num))), + have_error); } else - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s: \"%s\"", - "real", orig_num))); + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s: \"%s\"", + "real", orig_num))), + have_error); } /* skip trailing whitespace */ @@ -275,12 +287,19 @@ float4in(PG_FUNCTION_ARGS) /* if there is any junk left at the end of the string, bail out */ if (*endptr != '\0') - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s: \"%s\"", - "real", orig_num))); + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s: \"%s\"", + "real", orig_num))), + have_error); + + return val; +} - PG_RETURN_FLOAT4(val); +Datum +float4in(PG_FUNCTION_ARGS) +{ + PG_RETURN_FLOAT4(float4in_opt_error(PG_GETARG_CSTRING(0), NULL)); } /* @@ -340,17 +359,6 @@ float8in(PG_FUNCTION_ARGS) PG_RETURN_FLOAT8(float8in_internal(num, NULL, "double precision", num)); } -/* Convenience macro: set *have_error flag (if provided) or throw error */ -#define RETURN_ERROR(throw_error, have_error) \ -do { \ - if (have_error) { \ - *have_error = true; \ - return 0.0; \ - } else { \ - throw_error; \ - } \ -} while (0) - /* * float8in_internal_opt_error - guts of float8in() * diff --git a/src/include/utils/float.h b/src/include/utils/float.h index 4bf0e3ac07a..0ad4d9f3973 100644 --- a/src/include/utils/float.h +++ b/src/include/utils/float.h @@ -46,6 +46,7 @@ extern float8 float8in_internal(char *num, char **endptr_p, extern float8 float8in_internal_opt_error(char *num, char **endptr_p, const char *type_name, const char *orig_string, bool *have_error); +extern float float4in_opt_error(char *num, bool *have_error); extern char *float8out_internal(float8 num); extern int float4_cmp_internal(float4 a, float4 b); extern int float8_cmp_internal(float8 a, float8 b); -- 2.17.1