A database path containing ?, # or % opens the wrong file #55

Closed
opened 2026-09-21 09:17:53 +02:00 by clawbot · 2 comments
Collaborator

openDB (db.go) builds the SQLite connection string as
"file:" + path + "?_pragma=..." with the path unescaped. The driver
treats the first ? as the start of the options and # as a
fragment, so a database path containing ?, # or % — legal in a
Unix path, and the path comes straight from SFDUPES_DATABASE — opens
a different file than the one named, silently. scan then creates and
fills a database at the truncated path while reporting success against
the requested one.

Definition of done

  1. The path is escaped when the connection string is built (a
    net/url URL{Scheme: "file", Path: ...} or equivalent standard
    library call; nothing hand-rolled), so every byte of the path
    reaches SQLite as part of the file name.
  2. A test runs scan then report with SFDUPES_DATABASE pointing
    at a file whose name contains ?, #, % and a space, and
    asserts that exactly that file exists afterwards and no truncated
    sibling does.
  3. Relative database paths keep working.
  4. make check green.

Touches db.go; sequence after
#8, which rewrites the same
function.

Model: fable-5-1

`openDB` (`db.go`) builds the SQLite connection string as `"file:" + path + "?_pragma=..."` with the path unescaped. The driver treats the first `?` as the start of the options and `#` as a fragment, so a database path containing `?`, `#` or `%` — legal in a Unix path, and the path comes straight from `SFDUPES_DATABASE` — opens a different file than the one named, silently. `scan` then creates and fills a database at the truncated path while reporting success against the requested one. ## Definition of done 1. The path is escaped when the connection string is built (a `net/url` `URL{Scheme: "file", Path: ...}` or equivalent standard library call; nothing hand-rolled), so every byte of the path reaches SQLite as part of the file name. 2. A test runs `scan` then `report` with `SFDUPES_DATABASE` pointing at a file whose name contains `?`, `#`, `%` and a space, and asserts that exactly that file exists afterwards and no truncated sibling does. 3. Relative database paths keep working. 4. `make check` green. Touches `db.go`; sequence after https://git.eeqj.de/sneak/sfdupes/issues/8, which rewrites the same function. Model: fable-5-1
clawbot added this to the 1.0.0 milestone 2026-09-21 09:17:54 +02:00
Author
Collaborator

Plan (implementer's brief). There are now two connection strings, the read-write one for scan and the read-only one for report and trees (#8); both must escape the path the same way, through one standard-library call (net/url), not a hand-rolled escape. The test runs scan then report and trees against a database path holding ?, #, % and a space, and checks that exactly that file exists, along with its lock file (<path>.lock, #53), and no truncated sibling.

Model: opus-5-5

Plan (implementer's brief). There are now two connection strings, the read-write one for `scan` and the read-only one for `report` and `trees` (https://git.eeqj.de/sneak/sfdupes/issues/8); both must escape the path the same way, through one standard-library call (`net/url`), not a hand-rolled escape. The test runs `scan` then `report` and `trees` against a database path holding `?`, `#`, `%` and a space, and checks that exactly that file exists, along with its lock file (`<path>.lock`, https://git.eeqj.de/sneak/sfdupes/issues/53), and no truncated sibling. Model: opus-5-5
clawbot self-assigned this 2026-10-04 12:02:37 +02:00
Author
Collaborator

Implemented in #87: the database path is escaped through net/url in the one place both connection strings are built, without cleaning it, and a test covers an absolute path, a path starting with // and a relative path.

Model: opus-5-5

Implemented in https://git.eeqj.de/sneak/sfdupes/pulls/87: the database path is escaped through `net/url` in the one place both connection strings are built, without cleaning it, and a test covers an absolute path, a path starting with `//` and a relative path. Model: opus-5-5
Sign in to join this conversation.