Ticket #1782 (closed defect: fixed)

Opened 3 years ago

Last modified 3 years ago

[raster] rtpg_getSR fails for any spatial reference system not in EPSG.

Reported by: kempisty Owned by: dustymugs
Priority: medium Milestone: PostGIS 2.0.1
Component: raster Version: 2.0.x
Keywords: Cc:

Description

While trying to ST_Clip a raster against a geometry, using a custom spatial reference system (I gave it an arbitrary srid of 40000), I discovered that rtpg_getSR(int srid) fails for any reference system in spatial_ref_sys that does not have EPSG as its auth name. It never attempts to send the proj4text or srtext to GDAL.

Further, if you try to work around this by supplying a bogus 'EPSG' auth name and auth_srid for the custom reference system, tuptable->vals[i] goes out of bounds, segfaults, and brings down the postgres server.

In the code, the following query selects an EPSG id, a proj4text, and a srtext from spatial_ref_sys. (aligned it a bit for reading)

snprintf(sql, len, 
"SELECT 
   CASE 
      WHEN upper(auth_name) = 'EPSG' AND length(auth_srid::text) > 0 
      THEN upper(auth_name) || ':' || auth_srid 
      ELSE '' 
   END, 
   proj4text, 
   srtext 
FROM spatial_ref_sys 
WHERE srid = %d 
LIMIT 1"
, srid);
spi_result = SPI_execute(sql, TRUE, 0);

If auth_name is not EPSG, then this first column of the return value will be a zero length string.

Later...

tmp = SPI_getvalue(tuple, tupdesc, 1);
if (NULL == tmp || !strlen(tmp)) {
        elog(ERROR, "rtpg_getSR: Cannot find SRID (%d) in spatial_ref_sys.", srid);
        if (SPI_tuptable) SPI_freetuptable(tuptable);
        SPI_finish();        
        return NULL;
}

That code block sees the zero-length string in column 1 of the tuple returned from spatial_ref_sys. The function errors and returns NULL without ever trying to send proj4text or srtext to GDAL.

More bad things happen in the code around that check.

        tupdesc = SPI_tuptable->tupdesc;
        tuptable = SPI_tuptable;

        /* which tuple to use? */
        for (i = 0; i < 3; i++) {
                tuple = tuptable->vals[i];

                tmp = SPI_getvalue(tuple, tupdesc, 1);
                if (NULL == tmp || !strlen(tmp)) {
                        elog(ERROR, "rtpg_getSR: Cannot find SRID (%d) in spatial_ref_sys.", srid);
                        if (SPI_tuptable) SPI_freetuptable(tuptable);
                        SPI_finish();
                        return NULL;
                }

If we give this function a bogus EPSG and auth_srid, such as auth_name = 'EPSG' and auth_srid=40000, GDAL throws an error -- as expected -- and then we come back to the top for the second iteration through the FOR loop. Presumably, we're going to now try the proj4text. That's when we hit this:

        /* which tuple to use? */
        for (i = 0; i < 3; i++) {
                tuple = tuptable->vals[i];          

tuptable->vals has one array element for each row returned from our query. The query returns only one row, so there is only tuptable->vals 0. The code tries to reference tuptable->vals 1 , which is out of bounds, and segfaults.

It should loop through the three columns, like so:

        tupdesc = SPI_tuptable->tupdesc;
        tuptable = SPI_tuptable;
        tuple = tuptable->vals[0];

        /* which column to use? */
        for (i = 1; i < 4; i++) {
                tmp = SPI_getvalue(tuple, tupdesc, i);

Sorry for not just attaching some patches... I'm pretty new here, just getting my feet wet.

Change History

Changed 3 years ago by dustymugs

  • owner changed from pracine to dustymugs
  • status changed from new to assigned

Changed 3 years ago by dustymugs

  • status changed from assigned to closed
  • resolution set to fixed

Great catch and ticket kempisty! Thanks. I have no ideas what I was thinking when I wrote that block.

Fixed in r9647

Changed 3 years ago by kempisty

  • status changed from closed to reopened
  • resolution fixed deleted

r9647 takes care of the segfault. There is still the matter of handling the query into spatial_ref_sys. If auth_name isn't 'EPSG', the logic still returns an error without trying proj4text or srid.

At the moment, with the default contents of spatial_ref_sys, that's only a problem for srid=900913, auth_name="spatialreferencing.org". I suppose those people can use srid=3857 instead. In my case, for a custom srs with no auth_name, I will still get the error. rtpg_getSR will never try my proj4text or srtext strings in GDAL.

It looks like GDAL's SetFromUserInput?() will take EPSG: as well as EPSGA: and ESRI: and several other versions of shorthand. I'm not sure how many other people add their own entries into spatial_ref_sys. If they do, and if the auth_name is ESRI, or EPSGA, or null, they'll run into this.

Changed 3 years ago by dustymugs

  • status changed from reopened to closed
  • resolution set to fixed

Fixed in r9649

Changed 3 years ago by dustymugs

Additional fixes in r9709 and r9710.

Note: See TracTickets for help on using tickets.