sqlite: validate backup() source and URL-like paths - #65832
Draft
TrevorBurnham wants to merge 1 commit into
Draft
Conversation
backup() checked only that its first argument was an object before
unwrapping it as a DatabaseSync, so passing any other object
reinterpreted foreign memory as a database handle. Results ranged from
SIGSEGV to a spurious ERR_INVALID_STATE, depending on the object's
layout. It is the only unwrap site in node_sqlite.cc that takes a value
out of args[], and so the only one that V8's signature check for
args.This() does not already protect. DatabaseSync had no constructor
template on the Environment to test against, so add one alongside the
other sqlite classes and use it.
ValidateDatabasePath() treats any object with a string href as a URL
and asserted that the href parsed, aborting the process on, for
example, new DatabaseSync({ href: 'zzz' }). Reject an unparseable href
the same way other non-URL objects are rejected, and stop replacing an
exception thrown by the href getter with ERR_INVALID_ARG_TYPE.
Fixes: nodejs#65830
Signed-off-by: Trevor Burnham <trevorburnham@gmail.com>
Assisted-by: Claude Opus 5
Collaborator
|
Review requested:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes: #65830
Two argument-validation gaps in
node:sqlite, both reachable from a single call with no callbacks or timing involved.backup()reinterprets any object as aDatabaseSync*Backup()checked onlyargs[0]->IsObject()beforeASSIGN_OR_RETURN_UNWRAP. Passing a plain object crashed; passing a differentBaseObjectsubclass found a valid pointer in the internal field and readIsOpen()andconnection_at the wrong offsets:sourceDb{}SIGSEGV/SIGBUS[]FATAL ERROR: GetAlignedPointerFromInternalField() Internal field out of boundsdb.prepare('SELECT 1')SIGSEGV, occasionallyERR_INVALID_STATEdb.createSession()ERR_INVALID_STATE: database is not openThis is the only one of the unwrap sites in
src/node_sqlite.ccthat takes a value out ofargs[...]; the rest useargs.This()or an interceptor holder, both already covered by V8's signature check.DatabaseSyncwas the one class in the file with no constructor template stored on theEnvironment, soBackup()had nothing to test against. This adds theEnvironmentslot andDatabaseSync::GetConstructorTemplate()alongside the onesStatementSync,StatementSyncIterator, andSessionalready have, and checksHasInstance()before unwrapping.The error message changes from
The "sourceDb" argument must be an object.toThe "sourceDb" argument must be an instance of DatabaseSync., matching what the docs already specify for the parameter.ValidateDatabasePath()aborts on a duck-typed URLAny object with a string
hrefis treated as aURL, and the parse result was asserted rather than checked, sonew DatabaseSync({ href: 'zzz' })andbackup(db, { href: 'zzz' })hitCHECK(ada::can_parse(location))and aborted. An unparseablehrefnow falls through to the sameERR_INVALID_ARG_TYPEthat other non-URL objects get.While in that branch: a throwing
hrefgetter had its exception discarded and replaced byERR_INVALID_ARG_TYPE. It now propagates.Moved code
SetSideEffectFreeGetter()moved up to the top of the file soDatabaseSync::GetConstructorTemplate()can use it. The body is unchanged.Validation
All nine repro cases now throw
TypeErrors.parallel/test-sqlite*,parallel/test-webstorage*, andparallel/test-permission-sqlite-load-extensionpass, plus a check that a realURLpath,Symbol.for('sqlite-type'), andbackup()on aDatabaseSyncsubclass still behave as before.