Opened 13 years ago

Closed 12 years ago

Last modified 12 years ago

#1782 closed defect (fixed)

[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 (5)

comment:1 by dustymugs, 13 years ago

Owner: changed from pracine to dustymugs
Status: newassigned

comment:2 by dustymugs, 13 years ago

Resolution: fixed
Status: assignedclosed

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

Fixed in r9647

comment:3 by kempisty, 13 years ago

Resolution: fixed
Status: closedreopened

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.

comment:4 by dustymugs, 12 years ago

Resolution: fixed
Status: reopenedclosed

Fixed in r9649

comment:5 by dustymugs, 12 years ago

Additional fixes in r9709 and r9710.

Note: See TracTickets for help on using tickets.