-
-
Notifications
You must be signed in to change notification settings - Fork 36.4k
sqlite: reject deserialize() while in a callback #64796
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -613,8 +613,10 @@ added: | |
| Loads a serialized database into this connection, replacing the current | ||
| database. The deserialized database is writable. Existing prepared statements | ||
| are finalized before deserialization is attempted, even if the operation | ||
| subsequently fails. This method is a wrapper around | ||
| [`sqlite3_deserialize()`][]. | ||
| subsequently fails. An \[`ERR_INVALID_STATE`]\[] error is thrown if the method is | ||
| called while a statement is executing, for example from a user-defined function, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "while a statement is executing" doesn't quite describe the guard, which is A statement executing but no throw: for (const row of stmt.iterate()) {
db.deserialize(serialized); // succeeds
break; // → "statement has been finalized"
}No statement executing but it throws — an authorizer firing during db.setAuthorizer(() => { db.deserialize(serialized); return 0; });
db.prepare('SELECT v FROM t'); // → ERR_INVALID_STATEThe example list is also missing |
||
| an aggregate function, or an authorizer callback. This method is a wrapper | ||
| around [`sqlite3_deserialize()`][]. | ||
|
|
||
| ```mjs | ||
| import { DatabaseSync } from 'node:sqlite'; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1849,6 +1849,10 @@ void DatabaseSync::Deserialize(const FunctionCallbackInfo<Value>& args) { | |
| ASSIGN_OR_RETURN_UNWRAP(&db, args.This()); | ||
| Environment* env = Environment::GetCurrent(args); | ||
| THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open"); | ||
| THROW_AND_RETURN_ON_BAD_STATE( | ||
|
trivikr marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider changing let stmt;
db.function('f', (v) => { stmt.close(); return v; });
stmt = db.prepare('SELECT f(v) AS v FROM d');
stmt.all(); // → exit 139 (SIGSEGV)
|
||
| env, | ||
| db->IsInCallback(), | ||
| "database cannot be deserialized while in a callback"); | ||
|
|
||
| if (!args[0]->IsUint8Array()) { | ||
| THROW_ERR_INVALID_ARG_TYPE(env->isolate(), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The escaping silences the
no-undefined-referenceslint warning, but it also stops this being a link — it renders as literal bracket characters. Through micromark (the copy intools/lint-md/node_modules):So nodejs.org would show stray
[...][]brackets and no link to the error description.The underlying problem is just a missing link definition. This renders as a real anchor and passes
lint-mdcleanly (I verified exit 0 in a full checkout, so thenodejs-linkscross-file check is happy too):plus, in the definition block:
One gotcha: that definition needs to go immediately before
[`PRAGMA foreign_keys`]:. Putting it before[`SQLTagStore`]:instead tripsnodejs-linkswithUnordered reference ("ERR_INVALID_STATE" should be before "SQLITE_MAX_FUNCTION_ARG").