Skip to content

Commit 237baea

Browse files
committed
spatialite provider: fix segfault looking for nonexistent field
1 parent 1f6246e commit 237baea

File tree

2 files changed

+129
-95
lines changed

2 files changed

+129
-95
lines changed

src/providers/spatialite/qgsspatialiteprovider.cpp

+127-95
Original file line numberDiff line numberDiff line change
@@ -3262,35 +3262,43 @@ bool QgsSpatiaLiteProvider::prepareStatement(
32623262

32633263
QString primaryKey = !isQuery ? "ROWID" : quotedIdentifier( mPrimaryKey );
32643264

3265-
QString sql = QString( "SELECT %1" ).arg( primaryKey );
3266-
int colIdx = 1; // column 0 is primary key
3267-
for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
3265+
try
32683266
{
3269-
const QgsField & fld = field( *it );
3270-
QString fieldname = quotedIdentifier( fld.name() );
3271-
const QString type = fld.typeName().toLower();
3272-
if ( type.contains( "geometry" ) || type.contains( "point" ) ||
3273-
type.contains( "line" ) || type.contains( "polygon" ) )
3267+
QString sql = QString( "SELECT %1" ).arg( primaryKey );
3268+
int colIdx = 1; // column 0 is primary key
3269+
for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
32743270
{
3275-
fieldname = QString( "AsText(%1)" ).arg( fieldname );
3271+
const QgsField & fld = field( *it );
3272+
QString fieldname = quotedIdentifier( fld.name() );
3273+
const QString type = fld.typeName().toLower();
3274+
if ( type.contains( "geometry" ) || type.contains( "point" ) ||
3275+
type.contains( "line" ) || type.contains( "polygon" ) )
3276+
{
3277+
fieldname = QString( "AsText(%1)" ).arg( fieldname );
3278+
}
3279+
sql += "," + fieldname;
3280+
colIdx++;
32763281
}
3277-
sql += "," + fieldname;
3278-
colIdx++;
3279-
}
3280-
if ( fetchGeometry )
3281-
{
3282-
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
3283-
mGeomColIdx = colIdx;
3284-
}
3285-
sql += QString( " FROM %1" ).arg( mQuery );
3282+
if ( fetchGeometry )
3283+
{
3284+
sql += QString( ", AsBinary(%1)" ).arg( quotedIdentifier( mGeometryColumn ) );
3285+
mGeomColIdx = colIdx;
3286+
}
3287+
sql += QString( " FROM %1" ).arg( mQuery );
32863288

3287-
if ( !whereClause.isEmpty() )
3288-
sql += QString( " WHERE %1" ).arg( whereClause );
3289+
if ( !whereClause.isEmpty() )
3290+
sql += QString( " WHERE %1" ).arg( whereClause );
32893291

3290-
if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL ) != SQLITE_OK )
3292+
if ( sqlite3_prepare_v2( sqliteHandle, sql.toUtf8().constData(), -1, &stmt, NULL ) != SQLITE_OK )
3293+
{
3294+
// some error occurred
3295+
QgsMessageLog::logMessage( tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( sqlite3_errmsg( sqliteHandle ) ), tr( "SpatiaLite" ) );
3296+
return false;
3297+
}
3298+
}
3299+
catch ( SLFieldNotFound )
32913300
{
3292-
// some error occurred
3293-
QgsMessageLog::logMessage( tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( sqlite3_errmsg( sqliteHandle ) ), tr( "SpatiaLite" ) );
3301+
rewind();
32943302
return false;
32953303
}
32963304

@@ -3393,40 +3401,48 @@ QVariant QgsSpatiaLiteProvider::minimumValue( int index )
33933401
int columns;
33943402
char *errMsg = NULL;
33953403
QString minValue;
3404+
QString sql;
33963405

3397-
// get the field name
3398-
const QgsField & fld = field( index );
3406+
try
3407+
{
3408+
// get the field name
3409+
const QgsField & fld = field( index );
33993410

3400-
QString sql = QString( "SELECT Min(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
3411+
sql = QString( "SELECT Min(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
34013412

3402-
if ( !mSubsetString.isEmpty() )
3403-
{
3404-
sql += " WHERE ( " + mSubsetString + ")";
3405-
}
3413+
if ( !mSubsetString.isEmpty() )
3414+
{
3415+
sql += " WHERE ( " + mSubsetString + ")";
3416+
}
34063417

3407-
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
3408-
if ( ret != SQLITE_OK )
3409-
goto error;
3410-
if ( rows < 1 )
3411-
;
3412-
else
3413-
{
3414-
for ( i = 1; i <= rows; i++ )
3418+
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
3419+
if ( ret != SQLITE_OK )
3420+
goto error;
3421+
if ( rows < 1 )
3422+
;
3423+
else
3424+
{
3425+
for ( i = 1; i <= rows; i++ )
3426+
{
3427+
minValue = results[( i * columns ) + 0];
3428+
}
3429+
}
3430+
sqlite3_free_table( results );
3431+
3432+
if ( minValue.isEmpty() )
3433+
{
3434+
// NULL or not found
3435+
return QVariant( QString::null );
3436+
}
3437+
else
34153438
{
3416-
minValue = results[( i * columns ) + 0];
3439+
return convertValue( fld.type(), minValue );
34173440
}
34183441
}
3419-
sqlite3_free_table( results );
3420-
3421-
if ( minValue.isEmpty() )
3442+
catch ( SLFieldNotFound )
34223443
{
3423-
// NULL or not found
34243444
return QVariant( QString::null );
34253445
}
3426-
else
3427-
{
3428-
return convertValue( fld.type(), minValue );
3429-
}
34303446

34313447
error:
34323448
QgsMessageLog::logMessage( tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( errMsg ? errMsg : tr( "unknown cause" ) ), tr( "SpatiaLite" ) );
@@ -3448,39 +3464,47 @@ QVariant QgsSpatiaLiteProvider::maximumValue( int index )
34483464
int columns;
34493465
char *errMsg = NULL;
34503466
QString maxValue;
3467+
QString sql;
34513468

3452-
// get the field name
3453-
const QgsField & fld = field( index );
3469+
try
3470+
{
3471+
// get the field name
3472+
const QgsField & fld = field( index );
34543473

3455-
QString sql = QString( "SELECT Max(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
3474+
sql = QString( "SELECT Max(%1) FROM %2" ).arg( quotedIdentifier( fld.name() ) ).arg( mQuery );
34563475

3457-
if ( !mSubsetString.isEmpty() )
3458-
{
3459-
sql += " WHERE ( " + mSubsetString + ")";
3460-
}
3476+
if ( !mSubsetString.isEmpty() )
3477+
{
3478+
sql += " WHERE ( " + mSubsetString + ")";
3479+
}
34613480

3462-
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
3463-
if ( ret != SQLITE_OK )
3464-
goto error;
3465-
if ( rows < 1 )
3466-
;
3467-
else
3468-
{
3469-
for ( i = 1; i <= rows; i++ )
3481+
ret = sqlite3_get_table( sqliteHandle, sql.toUtf8().constData(), &results, &rows, &columns, &errMsg );
3482+
if ( ret != SQLITE_OK )
3483+
goto error;
3484+
if ( rows < 1 )
3485+
;
3486+
else
34703487
{
3471-
maxValue = results[( i * columns ) + 0];
3488+
for ( i = 1; i <= rows; i++ )
3489+
{
3490+
maxValue = results[( i * columns ) + 0];
3491+
}
34723492
}
3473-
}
3474-
sqlite3_free_table( results );
3493+
sqlite3_free_table( results );
34753494

3476-
if ( maxValue.isEmpty() )
3477-
{
3478-
// NULL or not found
3479-
return QVariant( QString::null );
3495+
if ( maxValue.isEmpty() )
3496+
{
3497+
// NULL or not found
3498+
return QVariant( QString::null );
3499+
}
3500+
else
3501+
{
3502+
return convertValue( fld.type(), maxValue );
3503+
}
34803504
}
3481-
else
3505+
catch ( SLFieldNotFound )
34823506
{
3483-
return convertValue( fld.type(), maxValue );
3507+
return QVariant( QString::null );
34843508
}
34853509

34863510
error:
@@ -3910,34 +3934,41 @@ bool QgsSpatiaLiteProvider::changeAttributeValues( const QgsChangedAttributesMap
39103934
// cycle through the changed attributes of the feature
39113935
for ( QgsAttributeMap::const_iterator siter = attrs.begin(); siter != attrs.end(); ++siter )
39123936
{
3913-
QString fieldName = field( siter.key() ).name();
3937+
try
3938+
{
3939+
QString fieldName = field( siter.key() ).name();
39143940

3915-
if ( !first )
3916-
sql += ",";
3917-
else
3918-
first = false;
3941+
if ( !first )
3942+
sql += ",";
3943+
else
3944+
first = false;
39193945

3920-
QVariant::Type type = siter->type();
3921-
if ( siter->toString().isEmpty() )
3922-
{
3923-
// assuming to be a NULL value
3924-
type = QVariant::Invalid;
3925-
}
3946+
QVariant::Type type = siter->type();
3947+
if ( siter->toString().isEmpty() )
3948+
{
3949+
// assuming to be a NULL value
3950+
type = QVariant::Invalid;
3951+
}
39263952

3927-
if ( type == QVariant::Invalid )
3928-
{
3929-
// binding a NULL value
3930-
sql += QString( "%1=NULL" ).arg( quotedIdentifier( fieldName ) );
3931-
}
3932-
else if ( type == QVariant::Int || type == QVariant::Double )
3933-
{
3934-
// binding a NUMERIC value
3935-
sql += QString( "%1=%2" ).arg( quotedIdentifier( fieldName ) ).arg( siter->toString() );
3953+
if ( type == QVariant::Invalid )
3954+
{
3955+
// binding a NULL value
3956+
sql += QString( "%1=NULL" ).arg( quotedIdentifier( fieldName ) );
3957+
}
3958+
else if ( type == QVariant::Int || type == QVariant::Double )
3959+
{
3960+
// binding a NUMERIC value
3961+
sql += QString( "%1=%2" ).arg( quotedIdentifier( fieldName ) ).arg( siter->toString() );
3962+
}
3963+
else
3964+
{
3965+
// binding a TEXT value
3966+
sql += QString( "%1=%2" ).arg( quotedIdentifier( fieldName ) ).arg( quotedValue( siter->toString() ) );
3967+
}
39363968
}
3937-
else
3969+
catch ( SLFieldNotFound )
39383970
{
3939-
// binding a TEXT value
3940-
sql += QString( "%1=%2" ).arg( quotedIdentifier( fieldName ) ).arg( quotedValue( siter->toString() ) );
3971+
// Field was missing - shouldn't happen
39413972
}
39423973
}
39433974
sql += QString( " WHERE ROWID=%1" ).arg( fid );
@@ -4865,7 +4896,8 @@ const QgsField & QgsSpatiaLiteProvider::field( int index ) const
48654896

48664897
if ( it == attributeFields.constEnd() )
48674898
{
4868-
QgsDebugMsg( QString( "Field %1 not found." ).arg( index ) );
4899+
QgsLogger::warning( QString( "FAILURE: Field %1 not found." ).arg( index ) );
4900+
throw SLFieldNotFound();
48694901
}
48704902

48714903
return it.value();

src/providers/spatialite/qgsspatialiteprovider.h

+2
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,8 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
453453
GEOS_3D_GEOMETRYCOLLECTION = -2147483641,
454454
};
455455

456+
struct SLFieldNotFound {}; //! Exception to throw
457+
456458
public:
457459
static QString quotedIdentifier( QString id );
458460
static QString quotedValue( QString value );

0 commit comments

Comments
 (0)