Index: src/vdbeblob.c ================================================================== --- src/vdbeblob.c +++ src/vdbeblob.c @@ -229,11 +229,11 @@ rc = sqlite3_step((sqlite3_stmt *)v); if( rc!=SQLITE_ROW ){ nAttempt++; rc = sqlite3_finalize((sqlite3_stmt *)v); sqlite3DbFree(db, zErr); - zErr = sqlite3MPrintf(db, sqlite3_errmsg(db)); + zErr = sqlite3MPrintf(db, "%s", sqlite3_errmsg(db)); v = 0; } } while( nAttempt<5 && rc==SQLITE_SCHEMA ); if( rc==SQLITE_ROW ){ @@ -276,11 +276,11 @@ blob_open_out: if( v && (rc!=SQLITE_OK || db->mallocFailed) ){ sqlite3VdbeFinalize(v); } - sqlite3Error(db, rc, zErr); + sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); sqlite3StackFree(db, pParse); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; Index: src/vtab.c ================================================================== --- src/vtab.c +++ src/vtab.c @@ -670,11 +670,11 @@ pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } db->pVTab = 0; }else{ - sqlite3Error(db, SQLITE_ERROR, zErr); + sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } pParse->declareVtab = 0; Index: test/incrblob.test ================================================================== --- test/incrblob.test +++ test/incrblob.test @@ -674,8 +674,17 @@ lappend rc $msg } {0 {}} do_test incrblob-8.7 { execsql {SELECT b FROM t1 WHERE a = 314159} } {etilqs} + +# The following test case exposes an instance in the blob code where +# an error message was set using a call similar to sqlite3_mprintf(zErr), +# where zErr is an arbitrary string. This is no good if the string contains +# characters that can be mistaken for printf() formatting directives. +# +do_test incrblob-9.1 { + list [catch { db incrblob t1 "A tricky column name %s%s" 1 } msg] $msg +} {1 {no such column: "A tricky column name %s%s"}} finish_test Index: test/vtab1.test ================================================================== --- test/vtab1.test +++ test/vtab1.test @@ -1160,8 +1160,23 @@ catchsql { ALTER TABLE echo_t2 RENAME TO another_name } } "1 {echo-vtab-error: the xRename method has failed}" unset echo_module_fail(xRename,t2) incr tn } + +# The following test case exposes an instance in sqlite3_declare_vtab() +# an error message was set using a call similar to sqlite3_mprintf(zErr), +# where zErr is an arbitrary string. This is no good if the string contains +# characters that can be mistaken for printf() formatting directives. +# +do_test vtab1-17.1 { + execsql { + PRAGMA writable_schema = 1; + INSERT INTO sqlite_master VALUES( + 'table', 't3', 't3', 0, 'INSERT INTO "%s%s" VALUES(1)' + ); + } + catchsql { CREATE VIRTUAL TABLE t4 USING echo(t3); } +} {1 {vtable constructor failed: t4}} unset -nocomplain echo_module_begin_fail finish_test