Merge branch 'prerelease'

This commit is contained in:
Nick Parker 2019-03-12 13:32:54 -05:00
commit db1128b9de
2 changed files with 60 additions and 20 deletions

View File

@ -1016,8 +1016,9 @@ static int sqlcipher_execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql)
void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
sqlite3 *db = sqlite3_context_db_handle(context);
const char* targetDb, *sourceDb;
int saved_flags = db->flags; /* Saved value of the db->flags */
int targetDb_idx = 0;
u64 saved_flags = db->flags; /* Saved value of the db->flags */
u32 saved_mDbFlags = db->mDbFlags; /* Saved value of the db->mDbFlags */
int saved_nChange = db->nChange; /* Saved value of db->nChange */
int saved_nTotalChange = db->nTotalChange; /* Saved value of db->nTotalChange */
u8 saved_mTrace = db->mTrace; /* Saved value of db->mTrace */
@ -1035,9 +1036,19 @@ void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **ar
targetDb = (const char*) sqlite3_value_text(argv[0]);
sourceDb = (argc == 2) ? (char *) sqlite3_value_text(argv[1]) : "main";
/* if the name of the target is not main, but the index returned is zero
there is a mismatch and we should not proceed */
targetDb_idx = sqlcipher_find_db_index(db, targetDb);
if(targetDb_idx == 0 && sqlite3StrICmp("main", targetDb) != 0) {
rc = SQLITE_ERROR;
pzErrMsg = sqlite3_mprintf("unknown database %s", targetDb);
goto end_of_export;
}
db->init.iDb = targetDb_idx;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_Defensive | SQLITE_CountRows);
db->xTrace = 0;
db->mTrace = 0;
@ -1045,26 +1056,26 @@ void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **ar
** in the temporary database.
*/
zSql = sqlite3_mprintf(
"SELECT 'CREATE TABLE %s.' || substr(sql,14) "
"SELECT sql "
" FROM %s.sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
" AND rootpage>0"
, targetDb, sourceDb);
, sourceDb);
rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
if( rc!=SQLITE_OK ) goto end_of_export;
sqlite3_free(zSql);
zSql = sqlite3_mprintf(
"SELECT 'CREATE INDEX %s.' || substr(sql,14)"
"SELECT sql "
" FROM %s.sqlite_master WHERE sql LIKE 'CREATE INDEX %%' "
, targetDb, sourceDb);
, sourceDb);
rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
if( rc!=SQLITE_OK ) goto end_of_export;
sqlite3_free(zSql);
zSql = sqlite3_mprintf(
"SELECT 'CREATE UNIQUE INDEX %s.' || substr(sql,21) "
"SELECT sql "
" FROM %s.sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %%'"
, targetDb, sourceDb);
, sourceDb);
rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
if( rc!=SQLITE_OK ) goto end_of_export;
sqlite3_free(zSql);
@ -1084,16 +1095,8 @@ void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **ar
if( rc!=SQLITE_OK ) goto end_of_export;
sqlite3_free(zSql);
/* Copy over the sequence table
/* Copy over the contents of the sequence table
*/
zSql = sqlite3_mprintf(
"SELECT 'DELETE FROM %s.' || quote(name) || ';' "
"FROM %s.sqlite_master WHERE name='sqlite_sequence' "
, targetDb, targetDb);
rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
if( rc!=SQLITE_OK ) goto end_of_export;
sqlite3_free(zSql);
zSql = sqlite3_mprintf(
"SELECT 'INSERT INTO %s.' || quote(name) "
"|| ' SELECT * FROM %s.' || quote(name) || ';' "
@ -1121,7 +1124,9 @@ void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **ar
zSql = NULL;
end_of_export:
db->init.iDb = 0;
db->flags = saved_flags;
db->mDbFlags = saved_mDbFlags;
db->nChange = saved_nChange;
db->nTotalChange = saved_nTotalChange;
db->xTrace = saved_xTrace;

View File

@ -228,6 +228,41 @@ db close
file delete -force test.db
file delete -force test2.db
do_test unencrypted-corrupt-to-encrypted-export {
sqlite_orig db test.db
execsql {
CREATE TABLE t1(a,b);
INSERT INTO t1 VALUES (1,2);
PRAGMA writable_schema = ON;
UPDATE sqlite_master SET sql = 'CREATE TABLE IF NOT EXISTS t1(a,b)'
WHERE tbl_name = 't1';
PRAGMA writable_schema = OFF;
INSERT INTO t1 VALUES (3,4);
SELECT * FROM t1;
ATTACH DATABASE 'test2.db' AS test2 KEY 'testkey2';
SELECT sqlcipher_export('test2');
}
db close
sqlite_orig db test2.db
execsql {
PRAGMA key = 'testkey2';
SELECT count(*) FROM sqlite_master;
SELECT count(*) FROM t1;
}
} {1 2}
db close
file delete -force test.db
file delete -force test2.db
# create an encrypted database, attach an unencrypted database
# with data in it, then import the data back into the encrypted DB
# and verify
@ -543,7 +578,7 @@ do_test export-attached-database {
SELECT a FROM fts WHERE b MATCH '1000000';
SELECT count(*) FROM t3;
}
} {1000 1000 1 1000 1001 1001 1000000 2}
} {1000 1000 2 1000 1001 1001 1000000 2}
db close
file delete -force test.db
file delete -force test2.db