Skip to content

Commit a76cfba

Browse files
committed
Add safeguards in LSN, numeric and float calculation for custom errors
Those data types use parsing and/or calculation wrapper routines which can generate some generic error messages in the event of a failure. The caller of these routines can also pass a pointer variable settable by the routine to track if an error has happened, letting the caller decide what to do in the event of an error and what error message to generate. Those routines have been slacking the initialization of the tracking flag, which can be confusing when reading the code, so add some safeguards against calls of these parsing routines which could lead to a dubious result. The LSN parsing gains an assertion to make sure that the tracking flag is set, while numeric and float paths initialize the flag to a saner state. Author: Jeevan Ladhe Reviewed-by: Álvaro Herrera, Michael Paquier Discussion: https://postgr.es/m/CAOgcT0NOM9oR0Hag_3VpyW0uF3iCU=BDUFSPfk9JrWXRcWQHqw@mail.gmail.com
1 parent 05ba837 commit a76cfba

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

src/backend/utils/adt/float.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ float8in(PG_FUNCTION_ARGS)
337337
}
338338

339339
/* Convenience macro: set *have_error flag (if provided) or throw error */
340-
#define RETURN_ERROR(throw_error) \
340+
#define RETURN_ERROR(throw_error, have_error) \
341341
do { \
342342
if (have_error) { \
343343
*have_error = true; \
@@ -376,6 +376,9 @@ float8in_internal_opt_error(char *num, char **endptr_p,
376376
double val;
377377
char *endptr;
378378

379+
if (have_error)
380+
*have_error = false;
381+
379382
/* skip leading whitespace */
380383
while (*num != '\0' && isspace((unsigned char) *num))
381384
num++;
@@ -388,7 +391,8 @@ float8in_internal_opt_error(char *num, char **endptr_p,
388391
RETURN_ERROR(ereport(ERROR,
389392
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
390393
errmsg("invalid input syntax for type %s: \"%s\"",
391-
type_name, orig_string))));
394+
type_name, orig_string))),
395+
have_error);
392396

393397
errno = 0;
394398
val = strtod(num, &endptr);
@@ -463,17 +467,18 @@ float8in_internal_opt_error(char *num, char **endptr_p,
463467
errnumber[endptr - num] = '\0';
464468
RETURN_ERROR(ereport(ERROR,
465469
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
466-
errmsg("\"%s\" is out of range for "
467-
"type double precision",
468-
errnumber))));
470+
errmsg("\"%s\" is out of range for type double precision",
471+
errnumber))),
472+
have_error);
469473
}
470474
}
471475
else
472476
RETURN_ERROR(ereport(ERROR,
473477
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
474478
errmsg("invalid input syntax for type "
475479
"%s: \"%s\"",
476-
type_name, orig_string))));
480+
type_name, orig_string))),
481+
have_error);
477482
}
478483
#ifdef HAVE_BUGGY_SOLARIS_STRTOD
479484
else
@@ -500,7 +505,8 @@ float8in_internal_opt_error(char *num, char **endptr_p,
500505
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
501506
errmsg("invalid input syntax for type "
502507
"%s: \"%s\"",
503-
type_name, orig_string))));
508+
type_name, orig_string))),
509+
have_error);
504510

505511
return val;
506512
}

src/backend/utils/adt/numeric.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,6 +2605,9 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
26052605
Numeric res;
26062606
int rscale;
26072607

2608+
if (have_error)
2609+
*have_error = false;
2610+
26082611
/*
26092612
* Handle NaN
26102613
*/
@@ -2721,6 +2724,9 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
27212724
NumericVar arg2;
27222725
NumericVar result;
27232726

2727+
if (have_error)
2728+
*have_error = false;
2729+
27242730
if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
27252731
return make_result(&const_nan);
27262732

@@ -3207,6 +3213,9 @@ numeric_int4_opt_error(Numeric num, bool *have_error)
32073213
NumericVar x;
32083214
int32 result;
32093215

3216+
if (have_error)
3217+
*have_error = false;
3218+
32103219
/* XXX would it be better to return NULL? */
32113220
if (NUMERIC_IS_NAN(num))
32123221
{
@@ -6249,6 +6258,9 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
62496258
int n;
62506259
Size len;
62516260

6261+
if (have_error)
6262+
*have_error = false;
6263+
62526264
if (sign == NUMERIC_NAN)
62536265
{
62546266
result = (Numeric) palloc(NUMERIC_HDRSZ_SHORT);

src/backend/utils/adt/pg_lsn.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ pg_lsn_in_internal(const char *str, bool *have_error)
3434
off;
3535
XLogRecPtr result;
3636

37+
Assert(have_error != NULL);
38+
*have_error = false;
39+
3740
/* Sanity check input format. */
3841
len1 = strspn(str, "0123456789abcdefABCDEF");
3942
if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')

0 commit comments

Comments
 (0)