[postgis-tickets] r16454 - Liblwgeom: Fix memory leaks

Raul raul at rmr.ninja
Fri Mar 9 09:43:13 PST 2018


Author: algunenano
Date: 2018-03-09 09:43:12 -0800 (Fri, 09 Mar 2018)
New Revision: 16454

Modified:
   trunk/liblwgeom/lwalgorithm.c
   trunk/liblwgeom/lwgeodetic.c
   trunk/liblwgeom/lwgeom.c
   trunk/liblwgeom/lwgeom_geos.c
   trunk/liblwgeom/lwgeom_geos_clean.c
   trunk/liblwgeom/lwlinearreferencing.c
   trunk/liblwgeom/lwtree.c
Log:
Liblwgeom: Fix memory leaks

Closes #4043
Closes #https://github.com/postgis/postgis/pull/230


Modified: trunk/liblwgeom/lwalgorithm.c
===================================================================
--- trunk/liblwgeom/lwalgorithm.c	2018-03-09 15:37:02 UTC (rev 16453)
+++ trunk/liblwgeom/lwalgorithm.c	2018-03-09 17:43:12 UTC (rev 16454)
@@ -466,6 +466,9 @@
 	int cross_right = 0;
 	int first_cross = 0;
 	int this_cross = 0;
+#if POSTGIS_DEBUG_LEVEL >= 4
+	char *geom_ewkt;
+#endif
 
 	pa1 = (POINTARRAY*)l1->points;
 	pa2 = (POINTARRAY*)l2->points;
@@ -474,8 +477,14 @@
 	if ( pa1->npoints < 2 || pa2->npoints < 2 )
 		return LINE_NO_CROSS;
 
-	LWDEBUGF(4, "l1 = %s", lwgeom_to_ewkt((LWGEOM*)l1));
-	LWDEBUGF(4, "l2 = %s", lwgeom_to_ewkt((LWGEOM*)l2));
+#if POSTGIS_DEBUG_LEVEL >= 4
+	geom_ewkt = lwgeom_to_ewkt((LWGEOM*)l1);
+	LWDEBUGF(4, "l1 = %s", geom_ewkt);
+	lwfree(geom_ewkt);
+	geom_ewkt = lwgeom_to_ewkt((LWGEOM*)l2);
+	LWDEBUGF(4, "l2 = %s", geom_ewkt);
+	lwfree(geom_ewkt);
+#endif
 
 	/* Initialize first point of q */
 	q1 = getPoint2d_cp(pa2, 0);

Modified: trunk/liblwgeom/lwgeodetic.c
===================================================================
--- trunk/liblwgeom/lwgeodetic.c	2018-03-09 15:37:02 UTC (rev 16453)
+++ trunk/liblwgeom/lwgeodetic.c	2018-03-09 17:43:12 UTC (rev 16454)
@@ -307,8 +307,12 @@
 static int gbox_check_poles(GBOX *gbox)
 {
 	int rv = LW_FALSE;
+#if POSTGIS_DEBUG_LEVEL >= 4
+	char *gbox_str = gbox_to_string(gbox);
 	LWDEBUG(4, "checking poles");
-	LWDEBUGF(4, "gbox %s", gbox_to_string(gbox));
+	LWDEBUGF(4, "gbox %s", gbox_str);
+	lwfree(gbox_str);
+#endif
 	/* Z axis */
 	if ( gbox->xmin < 0.0 && gbox->xmax > 0.0 &&
 	     gbox->ymin < 0.0 && gbox->ymax > 0.0 )
@@ -2432,6 +2436,9 @@
 	GEOGRAPHIC_POINT gpt_to_test;
 	POINT2D pt_outside;
 	GBOX gbox;
+#if POSTGIS_DEBUG_LEVEL >= 4
+	char *geom_ewkt;
+#endif
 	gbox.flags = 0;
 
 	/* Nulls and empties don't contain anything! */
@@ -2461,8 +2468,14 @@
 
 	LWDEBUGF(4, "pt_outside POINT(%.18g %.18g)", pt_outside.x, pt_outside.y);
 	LWDEBUGF(4, "pt_to_test POINT(%.18g %.18g)", pt_to_test->x, pt_to_test->y);
-	LWDEBUGF(4, "polygon %s", lwgeom_to_ewkt((LWGEOM*)poly));
-	LWDEBUGF(4, "gbox %s", gbox_to_string(&gbox));
+#if POSTGIS_DEBUG_LEVEL >= 4
+	geom_ewkt = lwgeom_to_ewkt((LWGEOM*)poly);
+	LWDEBUGF(4, "polygon %s", geom_ewkt);
+	lwfree(geom_ewkt);
+	geom_ewkt = gbox_to_string(&gbox);
+	LWDEBUGF(4, "gbox %s", geom_ewkt);
+	lwfree(geom_ewkt);
+#endif
 
 	/* Not in outer ring? We're done! */
 	if ( ! ptarray_contains_point_sphere(poly->rings[0], &pt_outside, pt_to_test) )

Modified: trunk/liblwgeom/lwgeom.c
===================================================================
--- trunk/liblwgeom/lwgeom.c	2018-03-09 15:37:02 UTC (rev 16453)
+++ trunk/liblwgeom/lwgeom.c	2018-03-09 17:43:12 UTC (rev 16454)
@@ -2254,7 +2254,7 @@
 lwgeom_subdivide_recursive(const LWGEOM *geom, uint32_t maxvertices, uint32_t depth, LWCOLLECTION *col)
 {
 	const uint32_t maxdepth = 50;
-	GBOX *clip = gbox_copy(lwgeom_get_bbox(geom));
+	GBOX clip, subbox1, subbox2;
 	uint32_t nvertices = 0;
 	uint32_t i, n = 0;
 	uint32_t split_ordinate;
@@ -2263,16 +2263,12 @@
 	double pivot = DBL_MAX;
 	double center = DBL_MAX;
 	LWPOLY *lwpoly = NULL;
-
-	GBOX *subbox1;
-	GBOX *subbox2;
 	LWGEOM *clipped;
 
-	if (!clip) return 0;
+	gbox_duplicate(lwgeom_get_bbox(geom), &clip);
+	width = clip.xmax - clip.xmin;
+	height = clip.ymax - clip.ymin;
 
-	width = clip->xmax - clip->xmin;
-	height = clip->ymax - clip->ymin;
-
 	if ( geom->type == POLYHEDRALSURFACETYPE || geom->type == TINTYPE )
 		lwerror("%s: unsupported geometry type '%s'", __func__, lwtype_name(geom->type));
 
@@ -2289,14 +2285,14 @@
 
 	if (width == 0.0)
 	{
-		clip->xmax += FP_TOLERANCE;
-		clip->xmin -= FP_TOLERANCE;
+		clip.xmax += FP_TOLERANCE;
+		clip.xmin -= FP_TOLERANCE;
 		width = 2 * FP_TOLERANCE;
 	}
 	if (height == 0.0)
 	{
-		clip->ymax += FP_TOLERANCE;
-		clip->ymin -= FP_TOLERANCE;
+		clip.ymax += FP_TOLERANCE;
+		clip.ymin -= FP_TOLERANCE;
 		height = 2 * FP_TOLERANCE;
 	}
 
@@ -2334,9 +2330,9 @@
 
 	split_ordinate = (width > height) ? 0 : 1;
 	if (split_ordinate == 0)
-		center = (clip->xmin + clip->xmax) / 2;
+		center = (clip.xmin + clip.xmax) / 2;
 	else
-		center = (clip->ymin + clip->ymax) / 2;
+		center = (clip.ymin + clip.ymax) / 2;
 
 	if (geom->type == POLYGONTYPE)
 	{
@@ -2382,19 +2378,19 @@
 		}
 	}
 
-	subbox1 = gbox_copy(clip);
-	subbox2 = gbox_copy(clip);
+	gbox_duplicate(&clip, &subbox1);
+	gbox_duplicate(&clip, &subbox2);
 
 	if (pivot == DBL_MAX) pivot = center;
 
 	if (split_ordinate == 0)
-		subbox1->xmax = subbox2->xmin = pivot;
+		subbox1.xmax = subbox2.xmin = pivot;
 	else
-		subbox1->ymax = subbox2->ymin = pivot;
+		subbox1.ymax = subbox2.ymin = pivot;
 
 	++depth;
 
-	clipped = lwgeom_clip_by_rect(geom, subbox1->xmin, subbox1->ymin, subbox1->xmax, subbox1->ymax);
+	clipped = lwgeom_clip_by_rect(geom, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
 	if (clipped)
 	{
 		n += lwgeom_subdivide_recursive(clipped, maxvertices, depth, col);
@@ -2401,7 +2397,7 @@
 		lwgeom_free(clipped);
 	}
 
-	clipped = lwgeom_clip_by_rect(geom, subbox2->xmin, subbox2->ymin, subbox2->xmax, subbox2->ymax);
+	clipped = lwgeom_clip_by_rect(geom, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
 	if (clipped)
 	{
 		n += lwgeom_subdivide_recursive(clipped, maxvertices, depth, col);

Modified: trunk/liblwgeom/lwgeom_geos.c
===================================================================
--- trunk/liblwgeom/lwgeom_geos.c	2018-03-09 15:37:02 UTC (rev 16453)
+++ trunk/liblwgeom/lwgeom_geos.c	2018-03-09 17:43:12 UTC (rev 16454)
@@ -882,10 +882,12 @@
 LWGEOM *
 lwgeom_clip_by_rect(const LWGEOM *geom1, double x1, double y1, double x2, double y2)
 {
-	LWGEOM* result;
+	LWGEOM *result;
 	LWGEOM *tmp;
+	LWGEOM *envelope = (LWGEOM*)lwpoly_construct_envelope(geom1->srid, x1, y1, x2, y2);
 
-	result = lwgeom_intersection(geom1, (LWGEOM *)lwpoly_construct_envelope(geom1->srid, x1, y1, x2, y2));
+	result = lwgeom_intersection(geom1, envelope);
+	lwgeom_free(envelope);
 
 	if (!result) return NULL;
 
@@ -1063,6 +1065,10 @@
 	uint32_t i, ngeoms;
 	int srid = GEOSGetSRID(geom_in);
 	Face** geoms;
+#if POSTGIS_DEBUG_LEVEL >= 3
+	LWGEOM *geos_geom;
+	char *geom_ewkt;
+#endif
 
 	vgeoms[0] = geom_in;
 	geos_result = GEOSPolygonize(vgeoms, 1);
@@ -1084,8 +1090,14 @@
 
 	ngeoms = GEOSGetNumGeometries(geos_result);
 
+#if POSTGIS_DEBUG_LEVEL >= 3
 	LWDEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms);
-	LWDEBUGF(3, "GEOSpolygonize: polygonized:%s", lwgeom_to_ewkt(GEOS2LWGEOM(geos_result, 0)));
+	geos_geom = GEOS2LWGEOM(geos_result, 0);
+	geom_ewkt = lwgeom_to_ewkt(geos_geom);
+	LWDEBUGF(3, "GEOSpolygonize: polygonized:%s", geom_ewkt);
+	lwgeom_free(geos_geom);
+	lwfree(geom_ewkt);
+#endif
 
 	/* No geometries in collection, early out */
 	if (ngeoms == 0)

Modified: trunk/liblwgeom/lwgeom_geos_clean.c
===================================================================
--- trunk/liblwgeom/lwgeom_geos_clean.c	2018-03-09 15:37:02 UTC (rev 16453)
+++ trunk/liblwgeom/lwgeom_geos_clean.c	2018-03-09 17:43:12 UTC (rev 16454)
@@ -335,6 +335,7 @@
 		point = LWGEOM_GEOS_getPointN(lines, 0);
 		if (!point) return NULL;
 		unioned = GEOSUnion(noded, point);
+		GEOSGeom_destroy(point);
 		if (!unioned)
 			return NULL;
 		else
@@ -359,6 +360,10 @@
 	GEOSGeom geos_cut_edges, geos_area, collapse_points;
 	GEOSGeometry* vgeoms[3]; /* One for area, one for cut-edges */
 	unsigned int nvgeoms = 0;
+#if POSTGIS_DEBUG_LEVEL >= 3
+	LWGEOM *geos_geom;
+	char *geom_ewkt;
+#endif
 
 	assert(GEOSGeomTypeId(gin) == GEOS_POLYGON || GEOSGeomTypeId(gin) == GEOS_MULTIPOLYGON);
 
@@ -365,7 +370,13 @@
 	geos_bound = GEOSBoundary(gin);
 	if (NULL == geos_bound) return NULL;
 
-	LWDEBUGF(3, "Boundaries: %s", lwgeom_to_ewkt(GEOS2LWGEOM(geos_bound, 0)));
+#if POSTGIS_DEBUG_LEVEL >= 3
+	geos_geom = GEOS2LWGEOM(geos_bound, 0);
+	geom_ewkt = lwgeom_to_ewkt(geos_geom);
+	LWDEBUGF(3, "Boundaries: %s", geom_ewkt);
+	lwgeom_free(geos_geom);
+	lwfree(geom_ewkt);
+#endif
 
 	/* Use noded boundaries as initial "cut" edges */
 
@@ -399,7 +410,13 @@
 			return NULL;
 		}
 
-		LWDEBUGF(3, "Boundaries input points %s", lwgeom_to_ewkt(GEOS2LWGEOM(pi, 0)));
+#if POSTGIS_DEBUG_LEVEL >= 3
+		geos_geom = GEOS2LWGEOM(pi, 0);
+		geom_ewkt = lwgeom_to_ewkt(geos_geom);
+		LWDEBUGF(3, "Boundaries input points %s", geom_ewkt);
+		lwgeom_free(geos_geom);
+		lwfree(geom_ewkt);
+#endif
 
 #ifdef LWGEOM_PROFILE_MAKEVALID
 		lwnotice("ST_MakeValid: extracting unique points from cut_edges");
@@ -414,7 +431,13 @@
 			return NULL;
 		}
 
-		LWDEBUGF(3, "Boundaries output points %s", lwgeom_to_ewkt(GEOS2LWGEOM(po, 0)));
+#if POSTGIS_DEBUG_LEVEL >= 3
+		geos_geom = GEOS2LWGEOM(po, 0);
+		geom_ewkt = lwgeom_to_ewkt(geos_geom);
+		LWDEBUGF(3, "Boundaries output points %s", geom_ewkt);
+		lwgeom_free(geos_geom);
+		lwfree(geom_ewkt);
+#endif
 
 #ifdef LWGEOM_PROFILE_MAKEVALID
 		lwnotice("ST_MakeValid: find collapse points");
@@ -430,7 +453,13 @@
 			return NULL;
 		}
 
-		LWDEBUGF(3, "Collapse points: %s", lwgeom_to_ewkt(GEOS2LWGEOM(collapse_points, 0)));
+#if POSTGIS_DEBUG_LEVEL >= 3
+		geos_geom = GEOS2LWGEOM(collapse_points, 0);
+		geom_ewkt = lwgeom_to_ewkt(geos_geom);
+		LWDEBUGF(3, "Collapse points: %s", geom_ewkt);
+		lwgeom_free(geos_geom);
+		lwfree(geom_ewkt);
+#endif
 
 #ifdef LWGEOM_PROFILE_MAKEVALID
 		lwnotice("ST_MakeValid: cleanup(1)");
@@ -441,7 +470,13 @@
 	}
 	GEOSGeom_destroy(geos_bound);
 
-	LWDEBUGF(3, "Noded Boundaries: %s", lwgeom_to_ewkt(GEOS2LWGEOM(geos_cut_edges, 0)));
+#if POSTGIS_DEBUG_LEVEL >= 3
+	geos_geom = GEOS2LWGEOM(geos_cut_edges, 0);
+	geom_ewkt = lwgeom_to_ewkt(geos_geom);
+	LWDEBUGF(3, "Noded Boundaries: %s", geom_ewkt);
+	lwgeom_free(geos_geom);
+	lwfree(geom_ewkt);
+#endif
 
 	/* And use an empty geometry as initial "area" */
 	geos_area = GEOSGeom_createEmptyPolygon();
@@ -767,6 +802,10 @@
 {
 	GEOSGeometry* gout;
 	char ret_char;
+#if POSTGIS_DEBUG_LEVEL >= 3
+	LWGEOM *geos_geom;
+	char *geom_ewkt;
+#endif
 
 	/*
 	 * Step 2: return what we got so far if already valid
@@ -781,16 +820,28 @@
 	}
 	else if (ret_char)
 	{
-		LWDEBUGF(3, "Geometry [%s] is valid. ", lwgeom_to_ewkt(GEOS2LWGEOM(gin, 0)));
+#if POSTGIS_DEBUG_LEVEL >= 3
+		geos_geom = GEOS2LWGEOM(gin, 0);
+		geom_ewkt = lwgeom_to_ewkt(geos_geom);
+		LWDEBUGF(3, "Geometry [%s] is valid. ", geom_ewkt);
+		lwgeom_free(geos_geom);
+		lwfree(geom_ewkt);
+#endif
 
 		/* It's valid at this step, return what we have */
 		return GEOSGeom_clone(gin);
 	}
 
+#if POSTGIS_DEBUG_LEVEL >= 3
+	geos_geom = GEOS2LWGEOM(gin, 0);
+	geom_ewkt = lwgeom_to_ewkt(geos_geom);
 	LWDEBUGF(3,
 		 "Geometry [%s] is still not valid: %s. Will try to clean up further.",
-		 lwgeom_to_ewkt(GEOS2LWGEOM(gin, 0)),
+		 geom_ewkt,
 		 lwgeom_geos_errmsg);
+	lwgeom_free(geos_geom);
+	lwfree(geom_ewkt);
+#endif
 
 	/*
 	 * Step 3 : make what we got valid

Modified: trunk/liblwgeom/lwlinearreferencing.c
===================================================================
--- trunk/liblwgeom/lwlinearreferencing.c	2018-03-09 15:37:02 UTC (rev 16453)
+++ trunk/liblwgeom/lwlinearreferencing.c	2018-03-09 17:43:12 UTC (rev 16454)
@@ -557,6 +557,9 @@
 	double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
 	char hasz, hasm;
 	char dims;
+#if POSTGIS_DEBUG_LEVEL >= 4
+	char *geom_ewkt;
+#endif
 
 	/* Null input, nothing we can do. */
 	if ( ! line )
@@ -576,8 +579,12 @@
 		to = t;
 	}
 
+#if POSTGIS_DEBUG_LEVEL >= 4
 	LWDEBUGF(4, "from = %g, to = %g, ordinate = %c", from, to, ordinate);
-	LWDEBUGF(4, "%s", lwgeom_to_ewkt((LWGEOM*)line));
+	geom_ewkt = lwgeom_to_ewkt((LWGEOM*)line);
+	LWDEBUGF(4, "%s", geom_ewkt);
+	lwfree(geom_ewkt);
+#endif
 
 	/* Asking for an ordinate we don't have. Error. */
 	if ( (ordinate == 'Z' && ! hasz) || (ordinate == 'M' && ! hasm) )

Modified: trunk/liblwgeom/lwtree.c
===================================================================
--- trunk/liblwgeom/lwtree.c	2018-03-09 15:37:02 UTC (rev 16453)
+++ trunk/liblwgeom/lwtree.c	2018-03-09 17:43:12 UTC (rev 16454)
@@ -930,7 +930,13 @@
 rect_tree_intersects_tree_recursive(RECT_NODE *n1, RECT_NODE *n2)
 {
 	int i, j;
-	LWDEBUGF(4,"n1 %s  n2 %s", rect_node_to_str(n1), rect_node_to_str(n2));
+#if POSTGIS_DEBUG_LEVEL >= 4
+	char *n1_str = rect_node_to_str(n1);
+	char *n2_str = rect_node_to_str(n2);
+	LWDEBUGF(4,"n1 %s  n2 %s", n1, n2);
+	lwfree(n1_str);
+	lwfree(n2_str);
+#endif
 	/* There can only be an edge intersection if the rectangles overlap */
 	if (rect_node_intersects(n1, n2))
 	{



More information about the postgis-tickets mailing list