Skip to content

Read a path entry as the path it spells, where that exists - #622

Merged
ronleizrowice-ant merged 4 commits into
mainfrom
fix/path-entries-read-as-paths
Oct 4, 2026
Merged

ronleizrowice-ant merged 4 commits into
mainfrom
fix/path-entries-read-as-paths

Conversation

@ronleizrowice-ant

@ronleizrowice-ant ronleizrowice-ant commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Last of three stacked pull requests replacing #608 (#620, #621, this); base: #621, the marker.

What

A folder may have *, ?, [ or ] in its name. Every entry inside one was read as a pattern alone, and lost: with /w writable, a denyWrite on a file in /w/[WIP] project left that file writable. An entry is now ALSO read as the path it spells where the part holding those characters exists, and as its tail pattern beneath an existing directory. The pattern reading stays. A deny takes every reading; an allow only a path that is there and no symbolic link.

Behaviour changes

  • Both config getters lstat for every pattern entry.
  • A default write directory is dropped under a denyRead inside a bracketed home.
  • The Linux wrapper keeps a direct caller's allowOnly pattern string only where it is such a path.
  • The message for a deny glob ending in a separator changed; still refused.
  • README, not covered: a macOS allow that is also a name allows the whole tree beneath it; the Linux monitor keeps its lists from initialize().

Tests

Real bubblewrap runs on Linux, both runtimes. macOS is profile text compared on Linux: nothing ran under sandbox-exec. The Windows function ran on Linux; five Windows-only cases were only read. 25 mutations, 24 caught, one equivalent.

Merge order

Conflicts with #569, #574, #575 and #607, whose one-argument expander drops anchor: pass { budget, anchor }. #581 is an alternative for brackets alone: land one.

A folder may have `*`, `?`, `[` or `]` in its name (`[WIP] project`), and
every entry inside one was read as a pattern alone and lost: a Linux
write entry was dropped, a read entry expanded to nothing, macOS compiled
a regex that misses the folder, Windows expanded a pattern beneath it to
nothing.

An entry with those characters is now also read as the path it spells
where the part that holds them exists on disk, and as its tail pattern
beneath an existing directory. The pattern reading stays. A deny takes
every reading that may hold; an allow takes one only for a path that is
there and is no symbolic link. `path-entries.ts` decides, for the
manager and the wrapper's fold on Linux, the profile builder on macOS and
`expandWindowsFsPaths` on Windows.
/tmp is a link to /private/tmp there, and a profile's rules go by real
paths. Nothing pinned that the anchor of a pattern beneath a bracketed
folder is canonicalised like any other path.
ronleizrowice-ant added a commit that referenced this pull request Sep 30, 2026
The walk's budget (#607), its shared listings (#627) and its steps (#628)
rewrite one code path, and the path entries of #620 to #622 sit on top of it.

Everything above the walk is a generator now: the read-deny expansion, the
function readDenyGlobExpander() returns, the allowRead expansion, the
resolution of read path entries, and withOtherReadings(), which calls the
expander once for each reading of an entry. The synchronous names finish
those on the spot.

In the walk the step comes first and the budget's clock is read after it,
before the next listing. The deadline is wall time, so turns given to other
work count against it: a wrap can be refused earlier for that, and a list is
never cut short.

The budget error is given its code around the delegated generator. An abort
is raised by the driver and does not pass through there, so a wrap with a
spent budget and an aborted signal rejects with the signal's reason.

A wrap that starts over makes a new budget and new listings, and reads the
new configuration's denyReadGlobBudget.

In the scan's catch the abort is looked at first, then what ripgrep listed.
Everything above the walk is a generator on main, so `withOtherReadings`
is one too: git did not mark it. `resolveReadPathEntries` is main's
generator with this branch's `kind`, and both expanders take
`(pattern, anchor)` and pass `{ anchor, listings }`.

One case of this branch asserted that what a pattern would match in a
folder of mode 000 can still be written. Below the working directory that
is no longer so: main's scan for dangerous names denies such a folder
whole. The case now runs from elsewhere as well.
antdres
antdres previously approved these changes Oct 4, 2026

@antdres antdres left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/stamp

Base automatically changed from feat/literal-path-marker to main October 4, 2026 17:39
@ronleizrowice-ant
ronleizrowice-ant dismissed antdres’s stale review October 4, 2026 17:39

The base branch was changed.

@antdres antdres left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/stamp

@ronleizrowice-ant
ronleizrowice-ant merged commit e025055 into main Oct 4, 2026
16 checks passed
@ronleizrowice-ant
ronleizrowice-ant deleted the fix/path-entries-read-as-paths branch October 4, 2026 18:22
ronleizrowice-ant added a commit that referenced this pull request Oct 4, 2026
#620, #621, #622 and #644 as merged upstream. The bundle held all four,
joined with the budget, so of the nine blocks git marks it keeps its own
side. What is new to it is the second commit of #644: comments.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants