v13-0018-error-safe-for-casting-geometry-data-type.patch
text/x-patch
Filename: v13-0018-error-safe-for-casting-geometry-data-type.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v13-0018
Subject: error safe for casting geometry data type
| File | + | − |
|---|---|---|
| contrib/btree_gist/btree_float4.c | 1 | 1 |
| contrib/btree_gist/btree_float8.c | 2 | 2 |
| src/backend/utils/adt/float.c | 52 | 52 |
| src/backend/utils/adt/geo_ops.c | 177 | 28 |
| src/include/utils/float.h | 81 | 31 |
From 494a2c19a623104ac7e5d1bcc7d4f4fb57b178e1 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Tue, 2 Dec 2025 15:25:29 +0800
Subject: [PATCH v13 18/20] error safe for casting geometry data type
select castsource::regtype, casttarget::regtype, pp.prosrc
from pg_cast pc join pg_proc pp on pp.oid = pc.castfunc
join pg_type pt on pt.oid = castsource
join pg_type pt1 on pt1.oid = casttarget
and pc.castfunc > 0 and pt.typarray <> 0
and pt.typnamespace = 'pg_catalog'::regnamespace
and pt1.typnamespace = 'pg_catalog'::regnamespace
and (pt.typcategory = 'G' or pt1.typcategory = 'G')
order by castsource::regtype, casttarget::regtype;
castsource | casttarget | prosrc
------------+------------+---------------
point | box | point_box
lseg | point | lseg_center
path | polygon | path_poly
box | point | box_center
box | lseg | box_diagonal
box | polygon | box_poly
box | circle | box_circle
polygon | point | poly_center
polygon | path | poly_path
polygon | box | poly_box
polygon | circle | poly_circle
circle | point | circle_center
circle | box | circle_box
circle | polygon |
(14 rows)
already error safe: point_box, box_diagonal, box_poly, poly_path, poly_box, circle_center
almost error safe: path_poly
patch make these functions error safe: lseg_center, box_center, box_circle, poly_center, poly_circle
circle_box
can not error safe: cast circle to polygon, because it's a SQL function
discussion: https://postgr.es/m/CACJufxHCMzrHOW=wRe8L30rMhB3sjwAv1LE928Fa7sxMu1Tx-g@mail.gmail.com
---
contrib/btree_gist/btree_float4.c | 2 +-
contrib/btree_gist/btree_float8.c | 4 +-
src/backend/utils/adt/float.c | 104 +++++++--------
src/backend/utils/adt/geo_ops.c | 205 ++++++++++++++++++++++++++----
src/include/utils/float.h | 112 +++++++++++-----
5 files changed, 313 insertions(+), 114 deletions(-)
diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c
index d9c859835da..a7325a7bb29 100644
--- a/contrib/btree_gist/btree_float4.c
+++ b/contrib/btree_gist/btree_float4.c
@@ -101,7 +101,7 @@ float4_dist(PG_FUNCTION_ARGS)
r = a - b;
if (unlikely(isinf(r)) && !isinf(a) && !isinf(b))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT4(fabsf(r));
}
diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c
index 567beede178..7c99b84de35 100644
--- a/contrib/btree_gist/btree_float8.c
+++ b/contrib/btree_gist/btree_float8.c
@@ -79,7 +79,7 @@ gbt_float8_dist(const void *a, const void *b, FmgrInfo *flinfo)
r = arg1 - arg2;
if (unlikely(isinf(r)) && !isinf(arg1) && !isinf(arg2))
- float_overflow_error();
+ float_overflow_error(NULL);
return fabs(r);
}
@@ -109,7 +109,7 @@ float8_dist(PG_FUNCTION_ARGS)
r = a - b;
if (unlikely(isinf(r)) && !isinf(a) && !isinf(b))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(fabs(r));
}
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index d746f961fd3..4a7623b1456 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -83,25 +83,25 @@ static void init_degree_constants(void);
* This does mean that you don't get a useful error location indicator.
*/
pg_noinline void
-float_overflow_error(void)
+float_overflow_error(struct Node *escontext)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value out of range: overflow")));
}
pg_noinline void
-float_underflow_error(void)
+float_underflow_error(struct Node *escontext)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value out of range: underflow")));
}
pg_noinline void
-float_zero_divide_error(void)
+float_zero_divide_error(struct Node *escontext)
{
- ereport(ERROR,
+ errsave(escontext,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
}
@@ -1460,9 +1460,9 @@ dsqrt(PG_FUNCTION_ARGS)
result = sqrt(arg1);
if (unlikely(isinf(result)) && !isinf(arg1))
- float_overflow_error();
+ float_overflow_error(NULL);
if (unlikely(result == 0.0) && arg1 != 0.0)
- float_underflow_error();
+ float_underflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1479,9 +1479,9 @@ dcbrt(PG_FUNCTION_ARGS)
result = cbrt(arg1);
if (unlikely(isinf(result)) && !isinf(arg1))
- float_overflow_error();
+ float_overflow_error(NULL);
if (unlikely(result == 0.0) && arg1 != 0.0)
- float_underflow_error();
+ float_underflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1617,24 +1617,24 @@ dpow(PG_FUNCTION_ARGS)
if (absx == 1.0)
result = 1.0;
else if (arg2 >= 0.0 ? (absx > 1.0) : (absx < 1.0))
- float_overflow_error();
+ float_overflow_error(NULL);
else
- float_underflow_error();
+ float_underflow_error(NULL);
}
}
else if (errno == ERANGE)
{
if (result != 0.0)
- float_overflow_error();
+ float_overflow_error(NULL);
else
- float_underflow_error();
+ float_underflow_error(NULL);
}
else
{
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
if (unlikely(result == 0.0) && arg1 != 0.0)
- float_underflow_error();
+ float_underflow_error(NULL);
}
}
@@ -1674,14 +1674,14 @@ dexp(PG_FUNCTION_ARGS)
if (unlikely(errno == ERANGE))
{
if (result != 0.0)
- float_overflow_error();
+ float_overflow_error(NULL);
else
- float_underflow_error();
+ float_underflow_error(NULL);
}
else if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
else if (unlikely(result == 0.0))
- float_underflow_error();
+ float_underflow_error(NULL);
}
PG_RETURN_FLOAT8(result);
@@ -1712,9 +1712,9 @@ dlog1(PG_FUNCTION_ARGS)
result = log(arg1);
if (unlikely(isinf(result)) && !isinf(arg1))
- float_overflow_error();
+ float_overflow_error(NULL);
if (unlikely(result == 0.0) && arg1 != 1.0)
- float_underflow_error();
+ float_underflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1745,9 +1745,9 @@ dlog10(PG_FUNCTION_ARGS)
result = log10(arg1);
if (unlikely(isinf(result)) && !isinf(arg1))
- float_overflow_error();
+ float_overflow_error(NULL);
if (unlikely(result == 0.0) && arg1 != 1.0)
- float_underflow_error();
+ float_underflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1778,7 +1778,7 @@ dacos(PG_FUNCTION_ARGS)
result = acos(arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1809,7 +1809,7 @@ dasin(PG_FUNCTION_ARGS)
result = asin(arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1835,7 +1835,7 @@ datan(PG_FUNCTION_ARGS)
*/
result = atan(arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1861,7 +1861,7 @@ datan2(PG_FUNCTION_ARGS)
*/
result = atan2(arg1, arg2);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1902,7 +1902,7 @@ dcos(PG_FUNCTION_ARGS)
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("input is out of range")));
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -1957,7 +1957,7 @@ dsin(PG_FUNCTION_ARGS)
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("input is out of range")));
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2137,7 +2137,7 @@ dacosd(PG_FUNCTION_ARGS)
result = 90.0 + asind_q1(-arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2174,7 +2174,7 @@ dasind(PG_FUNCTION_ARGS)
result = -asind_q1(-arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2206,7 +2206,7 @@ datand(PG_FUNCTION_ARGS)
result = (atan_arg1 / atan_1_0) * 45.0;
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2242,7 +2242,7 @@ datan2d(PG_FUNCTION_ARGS)
result = (atan2_arg1_arg2 / atan_1_0) * 45.0;
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2365,7 +2365,7 @@ dcosd(PG_FUNCTION_ARGS)
result = sign * cosd_q1(arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2487,7 +2487,7 @@ dsind(PG_FUNCTION_ARGS)
result = sign * sind_q1(arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2645,7 +2645,7 @@ dcosh(PG_FUNCTION_ARGS)
result = get_float8_infinity();
if (unlikely(result == 0.0))
- float_underflow_error();
+ float_underflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2665,7 +2665,7 @@ dtanh(PG_FUNCTION_ARGS)
result = tanh(arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2765,7 +2765,7 @@ derf(PG_FUNCTION_ARGS)
result = erf(arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2785,7 +2785,7 @@ derfc(PG_FUNCTION_ARGS)
result = erfc(arg1);
if (unlikely(isinf(result)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -2814,7 +2814,7 @@ dgamma(PG_FUNCTION_ARGS)
/* Per POSIX, an input of -Inf causes a domain error */
if (arg1 < 0)
{
- float_overflow_error();
+ float_overflow_error(NULL);
result = get_float8_nan(); /* keep compiler quiet */
}
else
@@ -2836,12 +2836,12 @@ dgamma(PG_FUNCTION_ARGS)
if (errno != 0 || isinf(result) || isnan(result))
{
if (result != 0.0)
- float_overflow_error();
+ float_overflow_error(NULL);
else
- float_underflow_error();
+ float_underflow_error(NULL);
}
else if (result == 0.0)
- float_underflow_error();
+ float_underflow_error(NULL);
}
PG_RETURN_FLOAT8(result);
@@ -2873,7 +2873,7 @@ dlgamma(PG_FUNCTION_ARGS)
* to report overflow, but it should never underflow.
*/
if (errno == ERANGE || (isinf(result) && !isinf(arg1)))
- float_overflow_error();
+ float_overflow_error(NULL);
PG_RETURN_FLOAT8(result);
}
@@ -3013,7 +3013,7 @@ float8_combine(PG_FUNCTION_ARGS)
tmp = Sx1 / N1 - Sx2 / N2;
Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp * tmp / N;
if (unlikely(isinf(Sxx)) && !isinf(Sxx1) && !isinf(Sxx2))
- float_overflow_error();
+ float_overflow_error(NULL);
}
/*
@@ -3080,7 +3080,7 @@ float8_accum(PG_FUNCTION_ARGS)
if (isinf(Sx) || isinf(Sxx))
{
if (!isinf(transvalues[1]) && !isinf(newval))
- float_overflow_error();
+ float_overflow_error(NULL);
Sxx = get_float8_nan();
}
@@ -3163,7 +3163,7 @@ float4_accum(PG_FUNCTION_ARGS)
if (isinf(Sx) || isinf(Sxx))
{
if (!isinf(transvalues[1]) && !isinf(newval))
- float_overflow_error();
+ float_overflow_error(NULL);
Sxx = get_float8_nan();
}
@@ -3393,7 +3393,7 @@ float8_regr_accum(PG_FUNCTION_ARGS)
(isinf(Sxy) &&
!isinf(transvalues[1]) && !isinf(newvalX) &&
!isinf(transvalues[3]) && !isinf(newvalY)))
- float_overflow_error();
+ float_overflow_error(NULL);
if (isinf(Sxx))
Sxx = get_float8_nan();
@@ -3545,15 +3545,15 @@ float8_regr_combine(PG_FUNCTION_ARGS)
tmp1 = Sx1 / N1 - Sx2 / N2;
Sxx = Sxx1 + Sxx2 + N1 * N2 * tmp1 * tmp1 / N;
if (unlikely(isinf(Sxx)) && !isinf(Sxx1) && !isinf(Sxx2))
- float_overflow_error();
+ float_overflow_error(NULL);
Sy = float8_pl(Sy1, Sy2);
tmp2 = Sy1 / N1 - Sy2 / N2;
Syy = Syy1 + Syy2 + N1 * N2 * tmp2 * tmp2 / N;
if (unlikely(isinf(Syy)) && !isinf(Syy1) && !isinf(Syy2))
- float_overflow_error();
+ float_overflow_error(NULL);
Sxy = Sxy1 + Sxy2 + N1 * N2 * tmp1 * tmp2 / N;
if (unlikely(isinf(Sxy)) && !isinf(Sxy1) && !isinf(Sxy2))
- float_overflow_error();
+ float_overflow_error(NULL);
}
/*
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 9101a720744..0c792c17e83 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -78,11 +78,14 @@ enum path_delim
/* Routines for points */
static inline void point_construct(Point *result, float8 x, float8 y);
static inline void point_add_point(Point *result, Point *pt1, Point *pt2);
+static inline bool point_add_point_safe(Point *result, Point *pt1, Point *pt2,
+ Node *escontext);
static inline void point_sub_point(Point *result, Point *pt1, Point *pt2);
static inline void point_mul_point(Point *result, Point *pt1, Point *pt2);
static inline void point_div_point(Point *result, Point *pt1, Point *pt2);
static inline bool point_eq_point(Point *pt1, Point *pt2);
static inline float8 point_dt(Point *pt1, Point *pt2);
+static inline float8 point_dt_safe(Point *pt1, Point *pt2, Node *escontext);
static inline float8 point_sl(Point *pt1, Point *pt2);
static int point_inside(Point *p, int npts, Point *plist);
@@ -109,6 +112,7 @@ static float8 lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg);
/* Routines for boxes */
static inline void box_construct(BOX *result, Point *pt1, Point *pt2);
static void box_cn(Point *center, BOX *box);
+static bool box_cn_safe(Point *center, BOX *box, Node* escontext);
static bool box_ov(BOX *box1, BOX *box2);
static float8 box_ar(BOX *box);
static float8 box_ht(BOX *box);
@@ -125,7 +129,7 @@ static float8 circle_ar(CIRCLE *circle);
/* Routines for polygons */
static void make_bound_box(POLYGON *poly);
-static void poly_to_circle(CIRCLE *result, POLYGON *poly);
+static bool poly_to_circle_safe(CIRCLE *result, POLYGON *poly, Node *escontext);
static bool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
static bool poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly);
static bool plist_same(int npts, Point *p1, Point *p2);
@@ -851,7 +855,8 @@ box_center(PG_FUNCTION_ARGS)
BOX *box = PG_GETARG_BOX_P(0);
Point *result = (Point *) palloc(sizeof(Point));
- box_cn(result, box);
+ if (!box_cn_safe(result, box, fcinfo->context))
+ PG_RETURN_NULL();
PG_RETURN_POINT_P(result);
}
@@ -871,10 +876,33 @@ box_ar(BOX *box)
static void
box_cn(Point *center, BOX *box)
{
- center->x = float8_div(float8_pl(box->high.x, box->low.x), 2.0);
- center->y = float8_div(float8_pl(box->high.y, box->low.y), 2.0);
+ (void) box_cn_safe(center, box, NULL);
}
+static bool
+box_cn_safe(Point *center, BOX *box, Node* escontext)
+{
+ float8 x;
+ float8 y;
+
+ x = float8_pl_safe(box->high.x, box->low.x, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ center->x = float8_div_safe(x, 2.0, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ y = float8_pl_safe(box->high.y, box->low.y, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ center->y = float8_div_safe(y, 2.0, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ return true;
+}
/* box_wd - returns the width (length) of the box
* (horizontal magnitude).
@@ -2004,6 +2032,23 @@ point_dt(Point *pt1, Point *pt2)
return hypot(float8_mi(pt1->x, pt2->x), float8_mi(pt1->y, pt2->y));
}
+static inline float8
+point_dt_safe(Point *pt1, Point *pt2, Node *escontext)
+{
+ float8 x;
+ float8 y;
+
+ x = float8_mi_safe(pt1->x, pt2->x, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return 0.0;
+
+ y = float8_mi_safe(pt1->y, pt2->y, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return 0.0;
+
+ return hypot(x, y);
+}
+
Datum
point_slope(PG_FUNCTION_ARGS)
{
@@ -2317,13 +2362,31 @@ lseg_center(PG_FUNCTION_ARGS)
{
LSEG *lseg = PG_GETARG_LSEG_P(0);
Point *result;
+ float8 x;
+ float8 y;
result = (Point *) palloc(sizeof(Point));
- result->x = float8_div(float8_pl(lseg->p[0].x, lseg->p[1].x), 2.0);
- result->y = float8_div(float8_pl(lseg->p[0].y, lseg->p[1].y), 2.0);
+ x = float8_pl_safe(lseg->p[0].x, lseg->p[1].x, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ result->x = float8_div_safe(x, 2.0, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ y = float8_pl_safe(lseg->p[0].y, lseg->p[1].y, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ result->y = float8_div_safe(y, 2.0, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
PG_RETURN_POINT_P(result);
+
+fail:
+ PG_RETURN_NULL();
}
@@ -4110,9 +4173,27 @@ construct_point(PG_FUNCTION_ARGS)
static inline void
point_add_point(Point *result, Point *pt1, Point *pt2)
{
- point_construct(result,
- float8_pl(pt1->x, pt2->x),
- float8_pl(pt1->y, pt2->y));
+ (void) point_add_point_safe(result, pt1, pt2, NULL);
+}
+
+static inline bool
+point_add_point_safe(Point *result, Point *pt1, Point *pt2,
+ Node *escontext)
+{
+ float8 x;
+ float8 y;
+
+ x = float8_pl_safe(pt1->x, pt2->x, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ y = float8_pl_safe(pt1->y, pt2->y, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ point_construct(result, x, y);
+
+ return true;
}
Datum
@@ -4458,7 +4539,7 @@ path_poly(PG_FUNCTION_ARGS)
/* This is not very consistent --- other similar cases return NULL ... */
if (!path->closed)
- ereport(ERROR,
+ ereturn(fcinfo->context, (Datum) 0,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("open path cannot be converted to polygon")));
@@ -4508,7 +4589,9 @@ poly_center(PG_FUNCTION_ARGS)
result = (Point *) palloc(sizeof(Point));
- poly_to_circle(&circle, poly);
+ if (!poly_to_circle_safe(&circle, poly, fcinfo->context))
+ PG_RETURN_NULL();
+
*result = circle.center;
PG_RETURN_POINT_P(result);
@@ -5191,14 +5274,30 @@ circle_box(PG_FUNCTION_ARGS)
box = (BOX *) palloc(sizeof(BOX));
- delta = float8_div(circle->radius, sqrt(2.0));
+ delta = float8_div_safe(circle->radius, sqrt(2.0), fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
- box->high.x = float8_pl(circle->center.x, delta);
- box->low.x = float8_mi(circle->center.x, delta);
- box->high.y = float8_pl(circle->center.y, delta);
- box->low.y = float8_mi(circle->center.y, delta);
+ box->high.x = float8_pl_safe(circle->center.x, delta, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ box->low.x = float8_mi_safe(circle->center.x, delta, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ box->high.y = float8_pl_safe(circle->center.y, delta, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ box->low.y = float8_mi_safe(circle->center.y, delta, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
PG_RETURN_BOX_P(box);
+
+fail:
+ PG_RETURN_NULL();
}
/* box_circle()
@@ -5209,15 +5308,35 @@ box_circle(PG_FUNCTION_ARGS)
{
BOX *box = PG_GETARG_BOX_P(0);
CIRCLE *circle;
+ float8 x;
+ float8 y;
circle = (CIRCLE *) palloc(sizeof(CIRCLE));
- circle->center.x = float8_div(float8_pl(box->high.x, box->low.x), 2.0);
- circle->center.y = float8_div(float8_pl(box->high.y, box->low.y), 2.0);
+ x = float8_pl_safe(box->high.x, box->low.x, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
- circle->radius = point_dt(&circle->center, &box->high);
+ circle->center.x = float8_div_safe(x, 2.0, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ y = float8_pl_safe(box->high.y, box->low.y, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ circle->center.y = float8_div_safe(y, 2.0, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
+
+ circle->radius = point_dt_safe(&circle->center, &box->high, fcinfo->context);
+ if (SOFT_ERROR_OCCURRED(fcinfo->context))
+ goto fail;
PG_RETURN_CIRCLE_P(circle);
+
+fail:
+ PG_RETURN_NULL();
}
@@ -5281,10 +5400,11 @@ circle_poly(PG_FUNCTION_ARGS)
* XXX This algorithm should use weighted means of line segments
* rather than straight average values of points - tgl 97/01/21.
*/
-static void
-poly_to_circle(CIRCLE *result, POLYGON *poly)
+static bool
+poly_to_circle_safe(CIRCLE *result, POLYGON *poly, Node *escontext)
{
int i;
+ float8 x;
Assert(poly->npts > 0);
@@ -5293,14 +5413,42 @@ poly_to_circle(CIRCLE *result, POLYGON *poly)
result->radius = 0;
for (i = 0; i < poly->npts; i++)
- point_add_point(&result->center, &result->center, &poly->p[i]);
- result->center.x = float8_div(result->center.x, poly->npts);
- result->center.y = float8_div(result->center.y, poly->npts);
+ {
+ if (!point_add_point_safe(&result->center,
+ &result->center,
+ &poly->p[i],
+ escontext))
+ return false;
+ }
+
+ result->center.x = float8_div_safe(result->center.x,
+ poly->npts,
+ escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ result->center.y = float8_div_safe(result->center.y,
+ poly->npts,
+ escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
for (i = 0; i < poly->npts; i++)
- result->radius = float8_pl(result->radius,
- point_dt(&poly->p[i], &result->center));
- result->radius = float8_div(result->radius, poly->npts);
+ {
+ x = point_dt_safe(&poly->p[i], &result->center, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ result->radius = float8_pl_safe(result->radius, x, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+ }
+
+ result->radius = float8_div_safe(result->radius, poly->npts, escontext);
+ if (SOFT_ERROR_OCCURRED(escontext))
+ return false;
+
+ return true;
}
Datum
@@ -5311,7 +5459,8 @@ poly_circle(PG_FUNCTION_ARGS)
result = (CIRCLE *) palloc(sizeof(CIRCLE));
- poly_to_circle(result, poly);
+ if (!poly_to_circle_safe(result, poly, fcinfo->context))
+ PG_RETURN_NULL();
PG_RETURN_CIRCLE_P(result);
}
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index fc2a9cf6475..c8abc7b3d78 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -30,9 +30,9 @@ extern PGDLLIMPORT int extra_float_digits;
/*
* Utility functions in float.c
*/
-pg_noreturn extern void float_overflow_error(void);
-pg_noreturn extern void float_underflow_error(void);
-pg_noreturn extern void float_zero_divide_error(void);
+extern void float_overflow_error(struct Node *escontext);
+extern void float_underflow_error(struct Node *escontext);
+extern void float_zero_divide_error(struct Node *escontext);
extern int is_infinite(float8 val);
extern float8 float8in_internal(char *num, char **endptr_p,
const char *type_name, const char *orig_string,
@@ -104,7 +104,22 @@ float4_pl(const float4 val1, const float4 val2)
result = val1 + val2;
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
- float_overflow_error();
+ float_overflow_error(NULL);
+
+ return result;
+}
+
+static inline float8
+float8_pl_safe(const float8 val1, const float8 val2, struct Node *escontext)
+{
+ float8 result;
+
+ result = val1 + val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ {
+ float_overflow_error(escontext);
+ return 0.0;
+ }
return result;
}
@@ -112,15 +127,10 @@ float4_pl(const float4 val1, const float4 val2)
static inline float8
float8_pl(const float8 val1, const float8 val2)
{
- float8 result;
-
- result = val1 + val2;
- if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
- float_overflow_error();
-
- return result;
+ return float8_pl_safe(val1, val2, NULL);
}
+
static inline float4
float4_mi(const float4 val1, const float4 val2)
{
@@ -128,7 +138,22 @@ float4_mi(const float4 val1, const float4 val2)
result = val1 - val2;
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
- float_overflow_error();
+ float_overflow_error(NULL);
+
+ return result;
+}
+
+static inline float8
+float8_mi_safe(const float8 val1, const float8 val2, struct Node *escontext)
+{
+ float8 result;
+
+ result = val1 - val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ {
+ float_overflow_error(escontext);
+ return 0.0;
+ }
return result;
}
@@ -136,15 +161,10 @@ float4_mi(const float4 val1, const float4 val2)
static inline float8
float8_mi(const float8 val1, const float8 val2)
{
- float8 result;
-
- result = val1 - val2;
- if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
- float_overflow_error();
-
- return result;
+ return float8_mi_safe(val1, val2, NULL);
}
+
static inline float4
float4_mul(const float4 val1, const float4 val2)
{
@@ -152,59 +172,89 @@ float4_mul(const float4 val1, const float4 val2)
result = val1 * val2;
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
- float_overflow_error();
+ float_overflow_error(NULL);
if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
- float_underflow_error();
+ float_underflow_error(NULL);
return result;
}
static inline float8
-float8_mul(const float8 val1, const float8 val2)
+float8_mul_safe(const float8 val1, const float8 val2, struct Node *escontext)
{
float8 result;
result = val1 * val2;
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
- float_overflow_error();
+ {
+ float_overflow_error(escontext);
+ return 0.0;
+ }
+
if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
- float_underflow_error();
+ {
+ float_underflow_error(escontext);
+ return 0.0;
+ }
return result;
}
+static inline float8
+float8_mul(const float8 val1, const float8 val2)
+{
+ return float8_mul_safe(val1, val2, NULL);
+}
+
static inline float4
float4_div(const float4 val1, const float4 val2)
{
float4 result;
if (unlikely(val2 == 0.0f) && !isnan(val1))
- float_zero_divide_error();
+ float_zero_divide_error(NULL);
result = val1 / val2;
if (unlikely(isinf(result)) && !isinf(val1))
- float_overflow_error();
+ float_overflow_error(NULL);
if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
- float_underflow_error();
+ float_underflow_error(NULL);
return result;
}
static inline float8
-float8_div(const float8 val1, const float8 val2)
+float8_div_safe(const float8 val1, const float8 val2, struct Node *escontext)
{
float8 result;
if (unlikely(val2 == 0.0) && !isnan(val1))
- float_zero_divide_error();
+ {
+ float_zero_divide_error(escontext);
+ return 0.0;
+ }
+
result = val1 / val2;
if (unlikely(isinf(result)) && !isinf(val1))
- float_overflow_error();
+ {
+ float_overflow_error(escontext);
+ return 0.0;
+ }
+
if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
- float_underflow_error();
+ {
+ float_underflow_error(escontext);
+ return 0.0;
+ }
return result;
}
+static inline float8
+float8_div(const float8 val1, const float8 val2)
+{
+ return float8_div_safe(val1, val2, NULL);
+}
+
/*
* Routines for NaN-aware comparisons
*
--
2.34.1