Open the downloaded snapshot database read-only, on a private temp dir (closes #162)
Restore and deep verify used to open the decrypted snapshot database read-write through the local-index constructor, which applied migrations against whatever the file carried, and left the decrypted file in the shared temp directory. A forged file could redefine what restore queries return, and an interrupted open left decrypted metadata on disk. Add database.OpenReadOnly: opens the file read-only (mode=ro) with query_only and trusted_schema=OFF, never applies schema files, and refuses a file whose schema carries a trigger, view or virtual table or lacks an expected table. Restore and deep verify now both use it, each inside its own private (0700) temp directory removed on every return path. pickNextDownload returns (FileID, bool) so a genuine nil-UUID file is not mistaken for "nothing left". Model: opus-4-8
This commit was merged in pull request #186.
This commit is contained in:
@@ -171,10 +171,13 @@ func (p *restorePlan) finishFile(fileID types.FileID) {
|
||||
// downloaded next, after which it — together with any other pending
|
||||
// files whose blob sets become empty — moves to the ready queue.
|
||||
//
|
||||
// The zero FileID return means nothing is pending.
|
||||
func (p *restorePlan) pickNextDownload() types.FileID {
|
||||
// The second return value is false when no file needs a download, so a
|
||||
// genuine file carrying the nil UUID is picked rather than mistaken for
|
||||
// "nothing left".
|
||||
func (p *restorePlan) pickNextDownload() (types.FileID, bool) {
|
||||
var best types.FileID
|
||||
|
||||
found := false
|
||||
bestCount := math.MaxInt
|
||||
|
||||
var bestID string
|
||||
@@ -188,14 +191,15 @@ func (p *restorePlan) pickNextDownload() types.FileID {
|
||||
}
|
||||
|
||||
idStr := id.String()
|
||||
if n < bestCount || (n == bestCount && (best.IsZero() || idStr < bestID)) {
|
||||
if !found || n < bestCount || (n == bestCount && idStr < bestID) {
|
||||
best = id
|
||||
found = true
|
||||
bestCount = n
|
||||
bestID = idStr
|
||||
}
|
||||
}
|
||||
|
||||
return best
|
||||
return best, found
|
||||
}
|
||||
|
||||
// blobsNeeded returns the uncached blob hashes for fileID in any order.
|
||||
|
||||
Reference in New Issue
Block a user