]> granicus.if.org Git - postgis/commitdiff
Fix another non-NULL safe array iteration within LWGEOM_collect_garray, as discovered...
authorMark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
Tue, 6 Oct 2009 10:15:39 +0000 (10:15 +0000)
committerMark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
Tue, 6 Oct 2009 10:15:39 +0000 (10:15 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@4604 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_accum.c
postgis/lwgeom_functions_basic.c

index 823ee1ef07adac8e7ecf8d2ab60fe919fac5d845..05e97d85737cd474f20fa8d05fb3f38c9ed90698 100644 (file)
@@ -236,7 +236,9 @@ pgis_geometry_collect_finalfn(PG_FUNCTION_ARGS)
        p = (pgis_abs*) PG_GETARG_POINTER(0);
 
        geometry_array = pgis_accum_finalfn(p, CurrentMemoryContext, fcinfo);
-       result = DirectFunctionCall1( LWGEOM_collect_garray, geometry_array );
+       result = PGISDirectFunctionCall1( LWGEOM_collect_garray, geometry_array );
+       if (!result)
+               PG_RETURN_NULL();
 
        PG_RETURN_DATUM(result);
 }
index 26ca1fc413aa300d2b68738cc739957671744f82..3fd59f6ec8901f82b33721adfbea8c32d5301b90 100644 (file)
@@ -1944,10 +1944,12 @@ Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS)
        PG_LWGEOM *result=NULL;
        LWGEOM **lwgeoms, *outlwg;
        unsigned int outtype;
-       int i;
+       int i, count;
        int SRID=-1;
        size_t offset;
        BOX2DFLOAT4 *box=NULL;
+       bits8 *bitmap; 
+       int bitmask;
 
        POSTGIS_DEBUG(2, "LWGEOM_collect_garray called.");
 
@@ -1985,89 +1987,115 @@ Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS)
         * array. Check input types to form output type.
         */
        lwgeoms = palloc(sizeof(LWGEOM *)*nelems);
+       count = 0;
        outtype = 0;
        offset = 0;
+       bitmap = ARR_NULLBITMAP(array);
+       bitmask = 1;
        for (i=0; i<nelems; i++)
        {
-               PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
-               unsigned int intype = TYPE_GETTYPE(geom->type);
-
-               offset += INTALIGN(VARSIZE(geom));
-
-               lwgeoms[i] = lwgeom_deserialize(SERIALIZED_FORM(geom));
-
-               POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: geom %d deserialized", i);
-
-               if ( ! i )
-               {
-                       /* Get first geometry SRID */
-                       SRID = lwgeoms[i]->SRID;
-
-                       /* COMPUTE_BBOX WHEN_SIMPLE */
-                       if ( lwgeoms[i]->bbox )
-                       {
-                               box = box2d_clone(lwgeoms[i]->bbox);
-                       }
-               }
-               else
+               /* Don't do anything for NULL values */ 
+               if ((bitmap && (*bitmap & bitmask) != 0) || !bitmap)
                {
-                       /* Check SRID homogeneity */
-                       if ( lwgeoms[i]->SRID != SRID )
+                       PG_LWGEOM *geom = (PG_LWGEOM *)(ARR_DATA_PTR(array)+offset);
+                       unsigned int intype = TYPE_GETTYPE(geom->type);
+       
+                       offset += INTALIGN(VARSIZE(geom));
+       
+                       lwgeoms[count] = lwgeom_deserialize(SERIALIZED_FORM(geom));
+       
+                       POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: geom %d deserialized", i);
+       
+                       if ( ! count )
                        {
-                               elog(ERROR,
-                                    "Operation on mixed SRID geometries");
-                               PG_RETURN_NULL();
+                               /* Get first geometry SRID */
+                               SRID = lwgeoms[count]->SRID;
+       
+                               /* COMPUTE_BBOX WHEN_SIMPLE */
+                               if ( lwgeoms[count]->bbox )
+                               {
+                                       box = box2d_clone(lwgeoms[count]->bbox);
+                               }
                        }
-
-                       /* COMPUTE_BBOX WHEN_SIMPLE */
-                       if ( box )
+                       else
                        {
-                               if ( lwgeoms[i]->bbox )
+                               /* Check SRID homogeneity */
+                               if ( lwgeoms[count]->SRID != SRID )
                                {
-                                       box->xmin = LW_MIN(box->xmin, lwgeoms[i]->bbox->xmin);
-                                       box->ymin = LW_MIN(box->ymin, lwgeoms[i]->bbox->ymin);
-                                       box->xmax = LW_MAX(box->xmax, lwgeoms[i]->bbox->xmax);
-                                       box->ymax = LW_MAX(box->ymax, lwgeoms[i]->bbox->ymax);
+                                       elog(ERROR,
+                                       "Operation on mixed SRID geometries");
+                                       PG_RETURN_NULL();
                                }
-                               else
+       
+                               /* COMPUTE_BBOX WHEN_SIMPLE */
+                               if ( box )
                                {
-                                       pfree(box);
-                                       box = NULL;
+                                       if ( lwgeoms[count]->bbox )
+                                       {
+                                               box->xmin = LW_MIN(box->xmin, lwgeoms[count]->bbox->xmin);
+                                               box->ymin = LW_MIN(box->ymin, lwgeoms[count]->bbox->ymin);
+                                               box->xmax = LW_MAX(box->xmax, lwgeoms[count]->bbox->xmax);
+                                               box->ymax = LW_MAX(box->ymax, lwgeoms[count]->bbox->ymax);
+                                       }
+                                       else
+                                       {
+                                               pfree(box);
+                                               box = NULL;
+                                       }
                                }
                        }
-               }
 
+                       lwgeom_dropSRID(lwgeoms[count]);
+                       lwgeom_drop_bbox(lwgeoms[count]);
+       
+                       /* Output type not initialized */
+                       if ( ! outtype )
+                       {
+                               /* Input is single, make multi */
+                               if ( intype < 4 ) outtype = intype+3;
+                               /* Input is multi, make collection */
+                               else outtype = COLLECTIONTYPE;
+                       }
+       
+                       /* Input type not compatible with output */
+                       /* make output type a collection */
+                       else if ( outtype != COLLECTIONTYPE && intype != outtype-3 )
+                       {
+                               outtype = COLLECTIONTYPE;
+                       }
 
-               lwgeom_dropSRID(lwgeoms[i]);
-               lwgeom_drop_bbox(lwgeoms[i]);
-
-               /* Output type not initialized */
-               if ( ! outtype )
-               {
-                       /* Input is single, make multi */
-                       if ( intype < 4 ) outtype = intype+3;
-                       /* Input is multi, make collection */
-                       else outtype = COLLECTIONTYPE;
-               }
+                       /* Advance NULL bitmap */
+                       if (bitmap)
+                       {
+                               bitmask <<= 1;
+                               if (bitmask == 0x100)
+                               {
+                                       bitmap++;
+                                       bitmask = 1;
+                               }
+                       }
 
-               /* Input type not compatible with output */
-               /* make output type a collection */
-               else if ( outtype != COLLECTIONTYPE && intype != outtype-3 )
-               {
-                       outtype = COLLECTIONTYPE;
+                       count++;
                }
-
        }
 
        POSTGIS_DEBUGF(3, "LWGEOM_collect_garray: outtype = %d", outtype);
 
-       outlwg = (LWGEOM *)lwcollection_construct(
-                    outtype, SRID,
-                    box, nelems, lwgeoms);
-
-       result = pglwgeom_serialize(outlwg);
-
-       PG_RETURN_POINTER(result);
+       /* If we have been passed a complete set of NULLs then return NULL */
+       if (!outtype)
+       {
+               PG_RETURN_NULL();
+       }
+       else
+       {
+               outlwg = (LWGEOM *)lwcollection_construct(
+                       outtype, SRID,
+                       box, count, lwgeoms);
+       
+               result = pglwgeom_serialize(outlwg);
+       
+               PG_RETURN_POINTER(result);
+       }
 }
 
 /**