Skip to content

fix(services/cloudflare-kv): strip only the root prefix from listed keys - #8048

Open
PDGGK wants to merge 1 commit into
apache:mainfrom
PDGGK:fix-cfkv-strip-root-prefix
Open

fix(services/cloudflare-kv): strip only the root prefix from listed keys#8048
PDGGK wants to merge 1 commit into
apache:mainfrom
PDGGK:fix-cfkv-strip-root-prefix

Conversation

@PDGGK

@PDGGK PDGGK commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

None filed — reporting and fixing together.

Rationale of this change

CloudflareKvLister removed the service root from listed keys with str::replace:

let mut name = name.replace(root.trim_start_matches('/'), "");

str::replace removes every occurrence anywhere in the string, not the leading one. So any key that repeats the root as an inner path segment comes back mangled:

root stored key listed as should be
/data/ data/backup/data/file.txt backup/file.txt backup/data/file.txt
/data/ xdata/file.txt xfile.txt xdata/file.txt

The second row shows it is not even anchored — a key merely containing the root loses that substring.

The same expression appeared at both call sites (build_entry_for_item for the key, and the non-recursive branch for self.path), so both now go through one relative_to_root helper.

On build_rel_path: that is what the s3/oss/cos/obs listers use here, and it was my first choice. It debug_assert!s that the path really does start with the root — a guarantee this service does not enforce on what the API returns — so a key that is not root-prefixed would panic in debug builds where replace previously left it alone. The helper therefore stays total and preserves that behaviour. Happy to switch to build_rel_path if you would rather have the assertion.

Are there any user-facing changes?

Yes: listed entry names are now correct for keys that repeat the root as an inner segment. Keys that do not are unaffected.

Tests

Three unit tests in lister.rs. Two fail against the previous expression:

test lister::tests::relative_to_root_does_not_match_mid_key ... FAILED
test lister::tests::relative_to_root_strips_only_the_prefix ... FAILED
test result: FAILED. 3 passed; 2 failed

The third covers the root itself and a bare / root and passes both before and after, which is what shows the other two are not trivially red.

With the fix: 5/5 pass (including the two pre-existing config tests). cargo fmt --check exits 0 and cargo clippy --all-targets is clean.

The lister removed the service root with str::replace, which removes
every occurrence anywhere in the key rather than the leading one. Any
key that repeats the root as an inner path segment came back mangled:
with root /data/, the key data/backup/data/file.txt was listed as
backup/file.txt. It also matches mid-key, so xdata/file.txt became
xfile.txt.

The same expression appeared at both call sites -- once for the key in
build_entry_for_item and once for self.path in the non-recursive branch
-- so both now go through one relative_to_root helper.

The sibling object-store listers use build_rel_path for this. That
helper debug_asserts the path really does start with the root, a
guarantee this service does not enforce on what the API returns, so the
helper here stays total and leaves a non-root-prefixed key alone --
matching what replace did in that case.

Three unit tests. Two of them fail against the previous expression; the
third covers the root itself and a bare "/" root and passes either way,
so the first two are not trivially red.
@PDGGK
PDGGK requested a review from Xuanwo as a code owner August 11, 2026 14:58
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. releases-note/fix The PR fixes a bug or has a title that begins with "fix" labels Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

releases-note/fix The PR fixes a bug or has a title that begins with "fix" size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant