-
-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CorruptError with backup #158
Comments
This step is ok, of course.
However, this is a problem in the context of encrypted databases. One restriction of the sqlite3mc encryption extension (and actually of SEE and SQLCipher as well) is that memory databases and temporary databases are not encrypted. Additionally, a restriction of the backup API is that you can't change page size and/or number of reserved bytes per page. That is, the page size and the number of reserved bytes per page of the source and target database need to be the same. The default cipher is To overcome this obstacle you can use one of the following approaches:
If you use one of the above solutions the error will go away.
This can be explained.
See the explanation above. |
I just did a test with two disk databases (no encryption) with different page sizes, and backed up one into the other. The content backup definitely happened when examining the content, and pragma page size continued to report the pre-backup page sizes. After a vacuum the reported page size did change to that of the backup source. Doing other tests where one of the disk databases is encrypted and the other isn't results in no errors, but then the encrypted one ends up corrupt. The bug here is not that there are combinations of memory, disk, plain, encrypted, different ciphers etc that cannot be backed up into each other, but that if you do so no error is returned with the backup API saying everything succeeded. You only later get a corrupt error after it is too late. |
IMHO this is a deficiency of the backup API, and I currently see no solution, except documenting what works and what not. |
You are producing a modified version of SQLite, so can't you detect this via code modification and return errors? Are you able to tell from within the VFS code if things like reserved bytes are correctly configured? Perhaps you could add a file control so the VFS level can be queried to check.
It would be desirable to have a code snippet to run to confirm the backup is ok. |
In principal, you are right. But it means to apply yet another patch to SQLite's code. The SQLCipher devs prohibit use of the backup API unless source and target database are both plain databases or both encrypted. I can introduce a similar check, so that
If the SQLite3MC VFS is used and a file is encrypted, it is possible to find out the number of reserved bytes (and other attributes of the cipher scheme). That is, it would be possible to provide the necessary information to an application. However, a user could then still start a backup operation, even if source and target database do not match. Therefore I think it is better to intercept the start of the backup operation in
|
That is by far the most desirable, and how I would expect things to work.
What I meant was a check if backup did not return an error which is what caused this issue in the first place. It resulted in a silently unusable database. Running It is probably worth having a separate Tips or similar page in the doc that suggests using You could also move the text relevant to #159 into there instead of duplicating it in both the C API and pragma sections. The #153 stuff is probably appropriate too. |
I have added a patch to perform this check. Commit utelle/apsw-sqlite3mc@b456b80 updates
The check introduced in
It certainly makes sense to add such a page.
Well, I think it is better to repeat the information in the pragma section. This saves a user from searching elsewhere. Nevertheless it can and probably should be added to a Tips page, too. |
Test code in apsw-sqlite3 committed.
This is one case where the backup works but you get CorruptError on the
|
Yes, indeed, it is unexpected that a backup with different numbers of reserved bytes succeeds. It could be that it works if the cipher scheme of the target database requires less reserved bytes per page than the source database. But this is not officially supported. In
Here the page sizes are different. AFAIK SQLite backup tries to set the page size of the target database to that of the source database, but this will not work for encrypted databases. The added check does not yet look at the page sizes. So, the check needs to be extended. |
Commit 879f4c6 added a check for compatible page sizes in the backup function. Closing. |
This uses a disk database
testdb
and sets an encryption key -dbmain
A memory database is then created and filled with gunk -
dbtmp
andfilldb
The memory database is backed up into (overwriting) the disk database.
A
SELECT
ondbmain
gives CorruptError.If the upper limit in
range
infilldb
is changed to 3 then the problem doesn't happen, so this is size dependent.The disk database is permanently corrupt. If you open it separately again, set the key, and try to read the contents you get CorruptError.
Reproduction script
The text was updated successfully, but these errors were encountered: