Skip to content

Fix isChildOf prefix match to require a path separator boundary#401

Open
samjanny wants to merge 1 commit into
hardcore-sushi:masterfrom
samjanny:fix/ischildof-separator-boundary
Open

Fix isChildOf prefix match to require a path separator boundary#401
samjanny wants to merge 1 commit into
hardcore-sushi:masterfrom
samjanny:fix/ischildof-separator-boundary

Conversation

@samjanny
Copy link
Copy Markdown

@samjanny samjanny commented Jun 1, 2026

Summary

Fixes a path-prefix confusion in PathUtils.isChildOf.

isChildOf determined the parent/child relationship with a bare
string-prefix comparison, without requiring a separator boundary:

isChildOf("/foobar", "/foo")  // returned true

The value feeds VolumeProvider.isChildDocument
(VolumeProvider.kt:119), which the Storage Access Framework calls to
verify that a documentId belongs to a granted tree. With the unsafe
usf_expose feature enabled and a SAF grant on a non-root subfolder,
an app could craft sibling documentIds (e.g. /foobar, /foo.txt)
and have them accepted as in-tree, reaching files never granted.

Fix

Require a separator boundary: a path is a child only when it equals
the parent plus a /-delimited segment. Root (/) and trailing-slash
parents are handled, and equal paths are no longer treated as a child
of themselves.

Impact on existing callers

The only other caller, the copy/move loop in BaseExplorerActivity,
operates on genuine descendants and is unaffected; removing the
self-as-child case avoids a redundant remap.

Testing

Verified the new logic against 12 edge cases with the Kotlin compiler
(original bug, genuine children, root parent, equal paths, trailing
slash). DroidFS has no automated test suite and a full Android build
(SDK + NDK r25c) was not run; the change is pure string-comparison
logic with no native dependencies.

isChildOf compared parent against child with a bare string-prefix
check, so isChildOf("/foobar", "/foo") wrongly returned true. The
result is used by VolumeProvider.isChildDocument, which the SAF
framework calls to confirm a documentId belongs to a granted subtree.
A false positive let an app holding a grant on /foo reach sibling
paths like /foobar.

Require a separator boundary: treat childPath as a descendant only
when it equals parentPath plus a '/' segment, handling the root and
trailing-slash cases. Also exclude equal paths, so a path is no
longer reported as a child of itself.
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.

1 participant