Closed julianhille closed 2 years ago
Hi @julianhille, I've done some tests and you're right. The issue is reproducible and it's intermittent. Take a look at these tests. Very inconsistent. And that's a HUGE problem. Intermittent issues are the worst because those are pretty much impossible to debug. Also way harder to do trial and error tests.
I'm currently on a very tight schedule and this needs a lot more debugging to be able to track down anything that might be causing the issue. I'll keep this issue as open for third-party help for the moment.
I have a system at hand were this always happens. I could try to debug this and come back. I had similar issues with my CPP/node pdf extension and so got a bit of experience debugging things like that.
Thanks for the quick response and confirmation.
Segmentation fault comes from sqlite3.c from sqlite3mcGetReservedWriteCipher.
codec->m_hasWriter
is a big negative number (which should not) and this ends up in an out of bounds when accessing: codecDescriptorTable[codec->m_writeCipherType-1]
.
What fixes it for me is do not use rekey
for an empty in memory database. If one yses key
it works totally fine.
If i fix the line to be
int reserved = (codec->m_hasWriteCipher == 1 && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1;
(see check against == 1 as intended) the seg fault is gone BUT we still get an abort with
sqlite3BtreeSetPageSize: Assertion `nReserve>=0 && nReserve<=255' failed.
somehow the codec value breaks in sqlite3_rekey_v2
This is all great information. sqlite3_rekey_v2
is a SQLite3MultipleCiphers function. Would you be willing to test an in-memory DB via the SQLite3MultipleCiphers CLI on that same system you managed to debug from? That would help us clarify if the issue's actually in SQLite3MultipleCiphers and not when it's executed through NAN.
Yes. Will get to it.
➜ SQLite3MultipleCiphers git:(main) ✗ ./sqlite3shell ":memory:"
SQLite version 3.39.2 2022-07-21 15:24:47 (SQLite3 Multiple Ciphers 1.4.7)
Enter ".help" for usage hints.
sqlite> ATTACH DATABASE ':memory:' AS aux1;
sqlite> PRAGMA rekey='password';
[1] 301894 segmentation fault (core dumped) ./sqlite3shell ":memory:"
build locally and only rekey it.
As documented here transient (i.e. in-memory) databases and temporary databases will not be encrypted. Only file-based databases (and journals) can be encrypted,
That said, it is simply a misuse to try to encrypt an in-memory database.
Nevertheless, an application should certainly not crash, even in case of misuse of a feature. So, I will address this issue soon.
Regarding the error analysis:
Segmentation fault comes from sqlite3.c from sqlite3mcGetReservedWriteCipher. codec->m_hasWriter is a big negative number (which should not) and this ends up in an out of bounds when accessing: codecDescriptorTable[codec->m_writeCipherType-1].
The reason for this is that function sqlite3_rekey
currently doesn't explicitly check for an in-memory database. Internally, the function tries to allocate a codec and link it to the associated database file (which does not exist for in-memory databases). Therefore, the codec is deleted (because usually the underlying vfs takes ownership of the codec structure). However, function sqlite3_rekey
makes use of the codec after it has been deleted - and this leads to a crash, of course.
If i fix the line to be
int reserved = (codec->m_hasWriteCipher == 1 && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1;
(see check against == 1 as intended) the seg fault is gone BUT we still get an abort with
This is not a fix, but only hides the real cause of the problem ...
sqlite3BtreeSetPageSize: Assertion `nReserve>=0 && nReserve<=255' failed.
... as this assert proves.
For the time being do not use "pragma key" or "pragma rekey" on an in-memory database - it isn't supported anyway.
Thanks @utelle for the insights.
This is not a fix, but only hides the real cause of the problem ...
Yes you are right and it was not meant as a fix for the issue more a test to see that the segfault is really originating in that piece.
@m4heshd what we want to do with this outcome?
i don't see other possible todos. Checking for pragma rekey or key if the database is an in-memory would be to error prone, i guess.
Commit https://github.com/utelle/SQLite3MultipleCiphers/commit/e1b82c1f9d09ba9576aadfcca1b23d4e0fdd28fe should fix the problem.
Since this project uses the SQLite3 Multiple Ciphers amalgamation sources, you probably want to wait for the next release. This may take a day or two.
@julianhille Thank you for debugging and your findings. @utelle Much appreciated you chiming in and providing a solution right away.
add a bit more prominent documentation about that
This IMO is a very rare case and unlikely to happen again 🤔. Since the functionality is already documented in SQLite3MC and a proper error is being thrown now, I'll keep the bs3mc documentation simple as it is for now.
Just merged the latest release of SQLite3MC and added some tests too. Changes are available in the latest beta release (v7.6.3-beta.0). Closing the issue.
This IMO is a very rare case and unlikely to happen again . Since the functionality is already documented in SQLite3MC and a proper error is being thrown now, I'll keep the bs3mc documentation simple as it is for now.
Not sure how likely/unlekliy that is, just wanted to say that i always use in-memory DBs for unit tests that is why i found this.
It seems a bit tricky to do trigger but this is what i did:
node Version: 16.16, also tried 16.13 better-sqlite3-multiple-ciphers: 7.6.2 OS: Kernel 5.15.0-41-generic, x86_64 GNU/Linux
This does not happen always. Most of the time it works.