Skip to content

🐛 Handle Windows-style extraction paths#2812

Merged
ChanTsune merged 1 commit into
mainfrom
codex/bsdtar-windows-path-compat
Mar 26, 2026
Merged

🐛 Handle Windows-style extraction paths#2812
ChanTsune merged 1 commit into
mainfrom
codex/bsdtar-windows-path-compat

Conversation

@ChanTsune
Copy link
Copy Markdown
Owner

@ChanTsune ChanTsune commented Mar 7, 2026

Summary by CodeRabbit

  • Bug Fixes
    • Improved Windows extraction safety: more robust stripping of absolute, drive and UNC prefixes; refined parent-directory detection; and corrected root/relative handling to prevent unsafe or mislocated extracts (including hardlink cases).
  • Tests
    • Added comprehensive Windows-style path tests covering drive prefixes, UNC forms, backslash handling, traversal rejection, and extraction outcomes.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 7, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Windows-aware path rewriting and bsdtar-style absolute-prefix stripping to extraction: new typed-path dependency, a RewrittenPath flow used by PathnameEditor, centralized unsafe-link detection, switch to UTF‑8-preserving Entry constructors, and Windows-specific tests.

Changes

Cohort / File(s) Summary
Dependency
cli/Cargo.toml
Added typed-path = "0.12".
Path handling & editor
cli/src/command/core/path.rs
Added RewrittenPath, rewrite_path_for_extraction, strip_absolute_path_bsdtar; moved absolute-prefix/root handling out of sanitizer; changed sanitization to component filtering; replaced lossy constructors with from_utf8_preserve_root; extended has_parent_dir_component logic to detect Windows parent-dir components; added pub(crate) fn is_unsafe_link_path; updated hardlink/root tracking; added extensive Windows-focused tests.
Extraction logic
cli/src/command/extract.rs
is_unsafe_link now delegates to crate::command::core::path::is_unsafe_link_path(...) (string-based rewrite + parent-dir check) instead of inspecting Path components.
Integration tests
cli/tests/cli/stdio/path_traversal.rs
Added sorted_entry_names helper and multiple stdio extraction tests for Windows drive-prefix stripping, \\?\UNC handling, non-Windows backslash semantics, and skipping entries that would traverse after prefix removal.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI (extract cmd)
    participant Editor as PathnameEditor
    participant Entry as EntryName/EntryReference
    participant Extractor as Extract logic

    CLI->>Editor: receive raw archive entry path
    Editor->>Editor: rewrite_path_for_extraction(raw) → RewrittenPath{path, had_root}
    Editor->>Entry: EntryReference::from_utf8_preserve_root(rewritten.path, had_root)
    Editor-->>CLI: return EntryReference
    CLI->>Extractor: pass EntryReference
    Extractor->>Extractor: is_unsafe_link_path(reference.as_str()) (uses rewrite + parent-dir check)
    Extractor-->>CLI: allow or skip extraction
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I nibble at backslashes, hop past a drive,

strip UNC hats so safe files arrive.
I rewrite paths with gentle care,
preserve UTF‑8 and root flags there.
No stray .. can hide!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Handle Windows-style extraction paths' directly describes the main change: adding Windows path prefix stripping, rewriting logic, and comprehensive tests for Windows-style path handling in extraction operations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/bsdtar-windows-path-compat

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical bug concerning the extraction of files with Windows-style paths. It introduces a new dependency, typed-path, and refactors the path processing logic to correctly identify and strip Windows-specific absolute path prefixes (like drive letters and UNC paths). This ensures that files are extracted to their intended relative locations while simultaneously bolstering security by preventing path traversal vulnerabilities that could arise from malformed Windows paths. The changes include new utility functions for path manipulation and a comprehensive suite of tests to verify the correctness and safety of the updated extraction mechanism.

Highlights

  • Windows Path Handling: Introduced robust logic to correctly parse and strip Windows-style absolute path prefixes (e.g., drive letters, UNC paths, \\?\) during file extraction, ensuring paths are handled as intended.
  • Security Enhancement: Enhanced path traversal checks (is_unsafe_link, has_parent_dir_component) to account for Windows-specific path components, ensuring that paths leading to parent directory traversal are correctly identified and rejected, even after prefix stripping.
  • Dependency Update: Integrated the typed-path crate to facilitate more precise and explicit handling of Windows path components, improving correctness and clarity.
  • Comprehensive Testing: Added extensive unit and integration tests to validate the new Windows path handling logic across various scenarios, including safe extractions and the rejection of unsafe paths.
Changelog
  • Cargo.lock
    • Updated to include typed-path dependency.
  • cli/Cargo.toml
    • Added typed-path crate version 0.12 as a dependency.
  • cli/src/command/core/path.rs
    • Imported typed_path utilities for Windows path handling.
    • Refactored path editing functions (edit_entry_name, edit_hardlink) to use a new rewrite_path_for_extraction method.
    • Introduced rewrite_path_for_extraction and RewrittenPath struct to manage path string and root stripping status.
    • Updated sanitize_preserve_curdir_str to simplify path component filtering.
    • Implemented strip_absolute_path_bsdtar to correctly identify and strip various Windows-style absolute path prefixes, including drive letters and UNC paths.
    • Enhanced has_parent_dir_component to detect Windows-style parent directory components.
    • Added comprehensive unit tests for Windows path handling, including stripping prefixes and detecting parent directory traversals.
  • cli/src/command/extract.rs
    • Updated is_unsafe_link to leverage new path utility functions for more robust Windows-style path traversal detection.
  • cli/tests/cli/stdio/path_traversal.rs
    • Added new integration tests to validate the extraction logic for various Windows-style paths, including drive letters, UNC prefixes, and path traversal scenarios.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces handling for Windows-style extraction paths, which is a great improvement for cross-platform compatibility. The changes are well-contained, primarily within cli/src/command/core/path.rs, and the new logic for stripping Windows path prefixes in strip_absolute_path_bsdtar seems correct and is thoroughly tested. The integration into the existing path editing functions is clean. The suggestion for a minor performance improvement to reduce allocations is still valid and included. Overall, this is a solid contribution.

Comment thread cli/src/command/core/path.rs Outdated
@github-actions github-actions Bot added dependencies Pull requests that update a dependency file cli This issue is about cli application labels Mar 7, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/src/command/core/path.rs`:
- Around line 45-47: The Windows absolute-prefix rewrite must run before
stripping components: call rewrite_path_for_extraction on the original path and
use its result as the input to transform_and_strip so drive letters/UNC/\\?\
prefixes aren't counted as leading components; update the three similar sites
that use transform_and_strip then rewrite (the occurrences around
transform_and_strip(...)? / rewrite_path_for_extraction(...) /
EntryName::from_utf8_preserve_root(...) and the other blocks at the later
locations) to perform rewrite_path_for_extraction first, then pass that
rewritten path into transform_and_strip, then continue to create
EntryName::from_utf8_preserve_root(rewritten.path.as_ref()) as before.

In `@cli/src/command/extract.rs`:
- Around line 1735-1737: The guard that enforces --no-allow-unsafe-links for
hardlinks currently only checks has_parent_dir_component on the rewritten path
and misses cases where a Windows root was stripped; modify the condition that
uses strip_absolute_path_bsdtar(...) so it uses the returned had_root flag as
part of the safety check (e.g., require blocking when had_root ||
crate::command::core::path::has_parent_dir_component(rewritten.as_ref())), and
ensure edit_hardlink() uses that combined boolean to reject unsafe hardlink
targets.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3754ce58-332d-45a3-a98a-141220cb8acb

📥 Commits

Reviewing files that changed from the base of the PR and between 6ff4344 and 40940c2.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • cli/Cargo.toml
  • cli/src/command/core/path.rs
  • cli/src/command/extract.rs
  • cli/tests/cli/stdio/path_traversal.rs

Comment thread cli/src/command/core/path.rs
Comment thread cli/src/command/extract.rs Outdated
@ChanTsune ChanTsune force-pushed the codex/bsdtar-windows-path-compat branch from 0924cd8 to ef27537 Compare March 8, 2026 09:52
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
cli/src/command/extract.rs (1)

1735-1737: ⚠️ Potential issue | 🟠 Major

This still misses Windows roots already stripped in edit_hardlink().

By the time the hardlink path reaches this helper, EntryReference is already the rewritten form (for example etc/hosts), so strip_absolute_path_bsdtar(reference.as_str()) can no longer recover the original c:/... or \\?\UNC\... root. --no-allow-unsafe-links still needs to incorporate the had_root boolean returned by edit_hardlink().

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/command/extract.rs` around lines 1735 - 1737, The check here
incorrectly recomputes had_root from the already-rewritten EntryReference so
Windows roots stripped earlier in edit_hardlink() are lost; modify the helper
signature (and its call sites) to accept and use the had_root flag produced by
edit_hardlink() instead of calling
strip_absolute_path_bsdtar(reference.as_str()) again, then return had_root ||
crate::command::core::path::has_parent_dir_component(rewritten.as_ref()); update
callers (the place that calls edit_hardlink() and this helper) to forward the
had_root boolean from edit_hardlink() so --no-allow-unsafe-links correctly
respects original Windows roots.
cli/src/command/core/path.rs (1)

45-47: ⚠️ Potential issue | 🟠 Major

Rewrite Windows prefixes before applying --strip-components.

These paths still go through transform_and_strip() first, so drive letters / UNC prefixes are counted as leading components before rewrite_path_for_extraction() sees them. c:/a/b with --strip-components=1 will still strip the drive prefix instead of the first real path segment, and //?/UNC/... can lose its recognizable shape before the rewrite logic runs.

Also applies to: 65-68

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/command/core/path.rs` around lines 45 - 47, The Windows path-rewrite
must run before any strip logic: currently transform_and_strip(...) is called
first so drive letters/UNC prefixes count as components and can be stripped;
instead call rewrite_path_for_extraction(...) on the original input first (so
UNC/\\?\\/drive prefixes are normalized/preserved), then pass the rewritten path
into transform_and_strip(...) (or adjust transform_and_strip to accept a
pre-rewritten Path/Stripped flag) and finally construct
EntryName::from_utf8_preserve_root(...) from that rewritten+stripped result;
apply the same reorder/fix at the other occurrence that uses transform_and_strip
-> rewrite_path_for_extraction -> EntryName::from_utf8_preserve_root.
🧹 Nitpick comments (1)
cli/tests/cli/stdio/path_traversal.rs (1)

546-691: Please add a hardlink regression for Windows-rooted targets.

These new cases cover entry-name rewriting, but not c:/... or \\?\UNC\... hardlink targets under --no-allow-unsafe-links. A focused stdio test there would catch the unsafe-link hole in cli/src/command/extract.rs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/tests/cli/stdio/path_traversal.rs` around lines 546 - 691, Add focused
stdio tests that assert hardlink targets with Windows-rooted names are treated
as unsafe and skipped when extraction is run with --no-allow-unsafe-links:
create two tests (e.g., stdio_extract_skips_windows_drive_hardlink_target and
stdio_extract_skips_windows_unc_hardlink_target) that use a helper to build an
archive containing a hardlink entry whose target is "c:/fileX" and
"\\\\?\\UNC\\server\\share\\fileY" respectively, run the same
cargo_bin_cmd!("pna") extract invocation but include the --no-allow-unsafe-links
flag, and assert that no files or links are created in out_dir; this will
exercise the code path in cli/src/command/extract.rs that validates link targets
and close the unsafe-link regression hole. Ensure the new tests use the same
setup()/sorted_entry_names helpers and mirror the style of
stdio_extract_rewrites_windows_drive_prefixed_entry_name and
stdio_extract_rewrites_windows_unc_prefixed_entry_name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@cli/src/command/core/path.rs`:
- Around line 45-47: The Windows path-rewrite must run before any strip logic:
currently transform_and_strip(...) is called first so drive letters/UNC prefixes
count as components and can be stripped; instead call
rewrite_path_for_extraction(...) on the original input first (so UNC/\\?\\/drive
prefixes are normalized/preserved), then pass the rewritten path into
transform_and_strip(...) (or adjust transform_and_strip to accept a
pre-rewritten Path/Stripped flag) and finally construct
EntryName::from_utf8_preserve_root(...) from that rewritten+stripped result;
apply the same reorder/fix at the other occurrence that uses transform_and_strip
-> rewrite_path_for_extraction -> EntryName::from_utf8_preserve_root.

In `@cli/src/command/extract.rs`:
- Around line 1735-1737: The check here incorrectly recomputes had_root from the
already-rewritten EntryReference so Windows roots stripped earlier in
edit_hardlink() are lost; modify the helper signature (and its call sites) to
accept and use the had_root flag produced by edit_hardlink() instead of calling
strip_absolute_path_bsdtar(reference.as_str()) again, then return had_root ||
crate::command::core::path::has_parent_dir_component(rewritten.as_ref()); update
callers (the place that calls edit_hardlink() and this helper) to forward the
had_root boolean from edit_hardlink() so --no-allow-unsafe-links correctly
respects original Windows roots.

---

Nitpick comments:
In `@cli/tests/cli/stdio/path_traversal.rs`:
- Around line 546-691: Add focused stdio tests that assert hardlink targets with
Windows-rooted names are treated as unsafe and skipped when extraction is run
with --no-allow-unsafe-links: create two tests (e.g.,
stdio_extract_skips_windows_drive_hardlink_target and
stdio_extract_skips_windows_unc_hardlink_target) that use a helper to build an
archive containing a hardlink entry whose target is "c:/fileX" and
"\\\\?\\UNC\\server\\share\\fileY" respectively, run the same
cargo_bin_cmd!("pna") extract invocation but include the --no-allow-unsafe-links
flag, and assert that no files or links are created in out_dir; this will
exercise the code path in cli/src/command/extract.rs that validates link targets
and close the unsafe-link regression hole. Ensure the new tests use the same
setup()/sorted_entry_names helpers and mirror the style of
stdio_extract_rewrites_windows_drive_prefixed_entry_name and
stdio_extract_rewrites_windows_unc_prefixed_entry_name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6d247c5b-95aa-4932-a25d-a7ab8b13b887

📥 Commits

Reviewing files that changed from the base of the PR and between 40940c2 and ef27537.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • cli/Cargo.toml
  • cli/src/command/core/path.rs
  • cli/src/command/extract.rs
  • cli/tests/cli/stdio/path_traversal.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • cli/Cargo.toml

@ChanTsune ChanTsune force-pushed the codex/bsdtar-windows-path-compat branch from ef27537 to 7beda9b Compare March 25, 2026 01:58
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
cli/src/command/core/path.rs (1)

125-140: Minor allocation inefficiency.

The into_owned() on line 127 followed by path.into_owned() on line 136 creates an extra allocation. Consider returning a borrowed Cow when possible:

♻️ Optional: reduce allocations
     fn rewrite_path_for_extraction<'a>(&self, path: &'a Path) -> RewrittenPath<'a> {
-        let raw = path.to_string_lossy().into_owned();
+        let raw = path.to_string_lossy();
         if self.absolute_paths {
             RewrittenPath {
-                path: Cow::Owned(raw),
+                path: Cow::Owned(raw.into_owned()),
                 had_root: false,
             }
         } else {
-            let (path, had_root) = strip_absolute_path_bsdtar(&raw);
+            let (stripped, had_root) = strip_absolute_path_bsdtar(&raw);
             RewrittenPath {
-                path: Cow::Owned(path.into_owned()),
+                path: match (raw, stripped) {
+                    (Cow::Borrowed(_), Cow::Borrowed(s)) => Cow::Owned(s.to_owned()),
+                    (Cow::Owned(o), Cow::Borrowed(s)) if s.len() == o.len() => Cow::Owned(o),
+                    (_, stripped) => Cow::Owned(stripped.into_owned()),
+                },
                 had_root,
             }
         }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/command/core/path.rs` around lines 125 - 140, The code calls
path.to_string_lossy().into_owned() then later path.into_owned(), causing an
extra allocation; change rewrite_path_for_extraction to keep the initial Cow
from Path::to_string_lossy() (e.g. let raw = path.to_string_lossy();) and return
that Cow directly in the absolute_paths branch or pass it into
strip_absolute_path_bsdtar(&raw) in the other branch so you avoid calling
into_owned twice; update the RewrittenPath construction to use the Cow values
returned by to_string_lossy/strip_absolute_path_bsdtar instead of creating
intermediate owned strings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cli/src/command/core/path.rs`:
- Around line 125-140: The code calls path.to_string_lossy().into_owned() then
later path.into_owned(), causing an extra allocation; change
rewrite_path_for_extraction to keep the initial Cow from Path::to_string_lossy()
(e.g. let raw = path.to_string_lossy();) and return that Cow directly in the
absolute_paths branch or pass it into strip_absolute_path_bsdtar(&raw) in the
other branch so you avoid calling into_owned twice; update the RewrittenPath
construction to use the Cow values returned by
to_string_lossy/strip_absolute_path_bsdtar instead of creating intermediate
owned strings.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7be01763-a16f-4624-9231-6ef038b14c11

📥 Commits

Reviewing files that changed from the base of the PR and between ef27537 and 7beda9b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • cli/Cargo.toml
  • cli/src/command/core/path.rs
  • cli/src/command/extract.rs
  • cli/tests/cli/stdio/path_traversal.rs
✅ Files skipped from review due to trivial changes (1)
  • cli/Cargo.toml

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
cli/src/command/core/path.rs (1)

1068-1072: Consider using the actual is_unsafe_link_path function in tests.

The is_unsafe_link_equivalent helper duplicates the logic of is_unsafe_link_path. Using the actual function would provide better test coverage of the public API.

♻️ Suggested change
-    /// Equivalent to is_unsafe_link logic for various link reference patterns.
-    fn is_unsafe_link_equivalent(s: &str) -> bool {
-        let (rewritten, had_root) = strip_absolute_path_bsdtar(s);
-        had_root || has_parent_dir_component(rewritten.as_ref())
-    }
-
     #[test]
-    fn unsafe_link_equivalent_detects_all_unsafe_patterns() {
+    fn is_unsafe_link_path_detects_all_unsafe_patterns() {
         // Windows drive prefix
-        assert!(is_unsafe_link_equivalent("C:/file"));
+        assert!(is_unsafe_link_path("C:/file"));
         // ... (update remaining calls)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/command/core/path.rs` around lines 1068 - 1072, Replace the
test-local helper is_unsafe_link_equivalent with direct calls to the public
function is_unsafe_link_path so tests exercise the actual API; locate tests that
call is_unsafe_link_equivalent (which currently uses strip_absolute_path_bsdtar
and has_parent_dir_component) and update them to call is_unsafe_link_path with
the same inputs, removing the duplicate logic and keeping assertions unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cli/src/command/core/path.rs`:
- Around line 1068-1072: Replace the test-local helper is_unsafe_link_equivalent
with direct calls to the public function is_unsafe_link_path so tests exercise
the actual API; locate tests that call is_unsafe_link_equivalent (which
currently uses strip_absolute_path_bsdtar and has_parent_dir_component) and
update them to call is_unsafe_link_path with the same inputs, removing the
duplicate logic and keeping assertions unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 747d4526-802f-477d-9349-0d2186c8528e

📥 Commits

Reviewing files that changed from the base of the PR and between 7beda9b and b6fdeb1.

📒 Files selected for processing (2)
  • cli/src/command/core/path.rs
  • cli/src/command/extract.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • cli/src/command/extract.rs

@ChanTsune ChanTsune force-pushed the codex/bsdtar-windows-path-compat branch from b6fdeb1 to 0ae693b Compare March 26, 2026 06:01
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
cli/src/command/core/path.rs (1)

686-694: Consider adding a test combining Windows-style paths with --strip-components.

The current tests verify Windows prefix stripping and component stripping separately. A test explicitly combining both (e.g., c:/a/b/c with strip_components=1) would document the expected interaction and help prevent future regressions.

📝 Example test
#[test]
fn editor_windows_prefix_with_strip_components() {
    let editor = PathnameEditor::new(Some(1), None, false, true);
    // c:/a/b/c: strip 1 component from a/b/c -> b/c (after prefix removal)
    let name = editor.edit_entry_name(Path::new("c:/a/b/c")).unwrap();
    // On both Unix and Windows, should strip "c:/" prefix then one component
    assert!(name.as_str() == "b/c" || name.as_str() == "a/b/c");
    // Note: exact behavior depends on whether prefix counts as component
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/command/core/path.rs` around lines 686 - 694, Add a unit test that
exercises Windows-style prefixes together with strip-components by creating a
PathnameEditor (use PathnameEditor::new with Some(1) for strip_components) and
calling edit_entry_name on a Windows path like "c:/a/b/c"; assert the resulting
string matches the expected post-prefix-and-component-stripped form (reference
PathnameEditor::new and PathnameEditor::edit_entry_name to locate where to add
the test) so the code documents and prevents regressions in the interaction
between Windows prefix stripping and component stripping.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cli/src/command/core/path.rs`:
- Around line 686-694: Add a unit test that exercises Windows-style prefixes
together with strip-components by creating a PathnameEditor (use
PathnameEditor::new with Some(1) for strip_components) and calling
edit_entry_name on a Windows path like "c:/a/b/c"; assert the resulting string
matches the expected post-prefix-and-component-stripped form (reference
PathnameEditor::new and PathnameEditor::edit_entry_name to locate where to add
the test) so the code documents and prevents regressions in the interaction
between Windows prefix stripping and component stripping.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c84117da-1132-44c5-8929-39c58786a2c9

📥 Commits

Reviewing files that changed from the base of the PR and between b6fdeb1 and 0ae693b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • cli/Cargo.toml
  • cli/src/command/core/path.rs
  • cli/src/command/extract.rs
  • cli/tests/cli/stdio/path_traversal.rs
✅ Files skipped from review due to trivial changes (1)
  • cli/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (2)
  • cli/src/command/extract.rs
  • cli/tests/cli/stdio/path_traversal.rs

@ChanTsune ChanTsune force-pushed the codex/bsdtar-windows-path-compat branch 2 times, most recently from 967fcb9 to 58df187 Compare March 26, 2026 06:56
@ChanTsune ChanTsune force-pushed the codex/bsdtar-windows-path-compat branch from 58df187 to a27382a Compare March 26, 2026 07:10
@ChanTsune ChanTsune merged commit 295d522 into main Mar 26, 2026
112 of 116 checks passed
@ChanTsune ChanTsune deleted the codex/bsdtar-windows-path-compat branch March 26, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli This issue is about cli application dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant