Skip to content

Commit

Permalink
Fix infinite recursion on proj < 6 builds
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 12, 2019
1 parent b6e4632 commit bc41f14
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 33 deletions.
44 changes: 28 additions & 16 deletions src/core/qgscoordinatereferencesystem.cpp
Expand Up @@ -669,7 +669,7 @@ bool QgsCoordinateReferenceSystem::loadFromDatabase( const QString &db, const QS
if ( !d->mIsValid )
{
if ( !d->mWkt.isEmpty() )
setWktString( d->mWkt );
setWktString( d->mWkt, false );
else
setProj4String( d->mProj4 );
}
Expand Down Expand Up @@ -1365,7 +1365,7 @@ void QgsCoordinateReferenceSystem::setProj4String( const QString &proj4String )
setMapUnits();
}

bool QgsCoordinateReferenceSystem::setWktString( const QString &wkt )
bool QgsCoordinateReferenceSystem::setWktString( const QString &wkt, bool allowProj4Fallback )
{
bool res = false;
d->mIsValid = false;
Expand Down Expand Up @@ -1406,6 +1406,10 @@ bool QgsCoordinateReferenceSystem::setWktString( const QString &wkt )
QgsDebugMsg( QStringLiteral( "UNUSED WKT: %1" ).arg( pWkt ) );
QgsDebugMsg( QStringLiteral( "---------------------------------------------------------------\n" ) );
}
else
{
d->mIsValid = true;
}
#endif

QgsReadWriteLocker locker( *sProj4CacheLock(), QgsReadWriteLocker::Unlocked );
Expand Down Expand Up @@ -1466,27 +1470,35 @@ bool QgsCoordinateReferenceSystem::setWktString( const QString &wkt )
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#if PROJ_VERSION_MAJOR<6
// create the proj4 structs needed for transforming
char *proj4src = nullptr;
OSRExportToProj4( d->mCRS, &proj4src );

//now that we have the proj4string, delegate to createFromProj4 so
// that we can try to fill in the remaining class members...
//create from Proj will set the isValidFlag
if ( !createFromProj4( proj4src ) )
if ( allowProj4Fallback )
{
CPLFree( proj4src );
d->mIsValid = false;
// create the proj4 structs needed for transforming
char *proj4src = nullptr;
OSRExportToProj4( d->mCRS, &proj4src );

//now that we have the proj4string, delegate to createFromProj4 so
// that we can try to fill in the remaining class members...
//create from Proj will set the isValidFlag
if ( !createFromProj4( proj4src ) )
{
CPLFree( proj4src );

#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(2,5,0)
// try fixed up version
OSRFixup( d->mCRS );
// try fixed up version
OSRFixup( d->mCRS );
#endif

OSRExportToProj4( d->mCRS, &proj4src );
OSRExportToProj4( d->mCRS, &proj4src );

createFromProj4( proj4src );
createFromProj4( proj4src );
}
CPLFree( proj4src );
}
else if ( d->mIsValid )
{
setMapUnits();
}
CPLFree( proj4src );
#endif
return d->mIsValid;
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgscoordinatereferencesystem.h
Expand Up @@ -766,7 +766,7 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
/**
* Set the WKT string
*/
bool setWktString( const QString &wkt );
bool setWktString( const QString &wkt, bool allowProj4Fallback = true );

/**
* Set this Geographic? flag
Expand Down
30 changes: 14 additions & 16 deletions tests/src/core/testqgscoordinatereferencesystem.cpp
Expand Up @@ -362,48 +362,46 @@ void TestQgsCoordinateReferenceSystem::createFromWktUnknown()
// try creating a crs from a non-standard WKT string (in this case, the invalid WKT definition of EPSG:31370 used by
// some ArcGIS versions: see https://github.com/OSGeo/PROJ/issues/1781
const QString wkt = QStringLiteral( R"""(PROJCS["Belge 1972 / Belgian Lambert 72",GEOGCS["Belge 1972",DATUM["Reseau_National_Belge_1972",SPHEROID["International 1924",6378388,297],AUTHORITY["EPSG","6313"]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["latitude_of_origin",90],PARAMETER["central_meridian",4.36748666666667],PARAMETER["standard_parallel_1",49.8333339],PARAMETER["standard_parallel_2",51.1666672333333],PARAMETER["false_easting",150000.01256],PARAMETER["false_northing",5400088.4378],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH]])""" );
crs.createFromWkt( wkt );
QVERIFY( crs.isValid() );
QgsDebugMsg( crs.toWkt() );

#if PROJ_VERSION_MAJOR>=6
const QString expectedWkt = wkt;
#else
// When used with proj < 6, a lossy conversion to proj string is used
QCOMPARE( crs.toWkt(), wkt );
const QString expectedWkt = QStringLiteral( R"""(PROJCS["unnamed",GEOGCS["International 1909 (Hayford)",DATUM["unknown",SPHEROID["intl",6378388,297],TOWGS84[-106.8686,52.2978,-103.7239,0.3366,-0.457,1.8422,-1.2747]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",49.8333339],PARAMETER["standard_parallel_2",51.1666672333333],PARAMETER["latitude_of_origin",90],PARAMETER["central_meridian",4.36748666666667],PARAMETER["false_easting",150000.01256],PARAMETER["false_northing",5400088.4378],UNIT["Meter",1]])""" );
#endif
QgsDebugMsg( expectedWkt );

crs.createFromWkt( wkt );
QVERIFY( crs.isValid() );
QgsDebugMsg( crs.toWkt() );
QCOMPARE( crs.toWkt(), expectedWkt );
QCOMPARE( crs.srsid(), static_cast< long >( USER_CRS_START_ID + 1 ) );
QCOMPARE( crs.authid(), QStringLiteral( "USER:100001" ) );
QCOMPARE( crs.mapUnits(), QgsUnitTypes::DistanceMeters );

// try creating new ones with same def
QgsCoordinateReferenceSystem crs2( QStringLiteral( "USER:100001" ) );
QVERIFY( crs2.isValid() );
#if PROJ_VERSION_MAJOR>=6
QCOMPARE( crs2.toWkt(), wkt );
#endif
QCOMPARE( crs2.toWkt(), expectedWkt );
QCOMPARE( crs2.mapUnits(), QgsUnitTypes::DistanceMeters );

QgsCoordinateReferenceSystem crs3;
crs3.createFromWkt( wkt );
QVERIFY( crs3.isValid() );
#if PROJ_VERSION_MAJOR>=6
QCOMPARE( crs3.toWkt(), wkt );
#endif
QCOMPARE( crs3.toWkt(), expectedWkt );
QCOMPARE( crs3.mapUnits(), QgsUnitTypes::DistanceMeters );

// force reads from database
QgsCoordinateReferenceSystem::invalidateCache();
QgsCoordinateReferenceSystem crs4( QStringLiteral( "USER:100001" ) );
QVERIFY( crs4.isValid() );
#if PROJ_VERSION_MAJOR>=6
QCOMPARE( crs4.toWkt(), wkt );
#endif
QCOMPARE( crs4.toWkt(), expectedWkt );
QCOMPARE( crs4.mapUnits(), QgsUnitTypes::DistanceMeters );

QgsCoordinateReferenceSystem crs5;
crs5.createFromWkt( wkt );
QVERIFY( crs5.isValid() );
#if PROJ_VERSION_MAJOR>=6
QCOMPARE( crs5.toWkt(), wkt );
#endif
QCOMPARE( crs5.toWkt(), expectedWkt );
QCOMPARE( crs5.mapUnits(), QgsUnitTypes::DistanceMeters );
}

Expand Down

0 comments on commit bc41f14

Please sign in to comment.