Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added warning when using restricted names in Windows. #8136

Merged
merged 1 commit into from
Apr 26, 2020

Conversation

hbina
Copy link
Contributor

@hbina hbina commented Apr 19, 2020

The implementation could have been better. I think there ought to be a way to only use the views into the OsString instead of creating a new one. I am new to Rust so any pointer will help ^^

@rust-highfive
Copy link

r? @Eh2406

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 19, 2020
@ehuss
Copy link
Contributor

ehuss commented Apr 19, 2020

Thanks for the PR!

What I would do is extract this code into a new function fn is_windows_reserved_path(path: &Path) -> bool, and place it in the restricted_names module. You can then just call that with entry_path.

Also, I don't think there should be any message for non-windows platforms. These filenames aren't a problem for non-windows users.

You'll need to place this in the chain_err closure so that it only runs when extraction fails.

@hbina
Copy link
Contributor Author

hbina commented Apr 22, 2020

@ehuss something like this?

Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

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

Can you write a test for this? Use Package to publish a package with an invalid filename, and then try to use it as a dependency, and then run cargo build. Let me know if you have any questions about writing tests.

Also, it would be good to reuse is_windows_reserved_path in cargo_package::check_filename.

@@ -81,3 +82,20 @@ pub fn validate_package_name(name: &str, what: &str, help: &str) -> CargoResult<
}
Ok(())
}

// Check the entire path for names reserved in Windows.
pub fn is_windows_reserved_path(path: &Path) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think instead of fold, it might be simpler to use any. Also, it's probably more correct to check every path component. So this function could maybe be rewritten as:

    path.iter()
        .filter_map(|component| component.to_str())
        .any(|component| {
            let stem = component.split('.').next().unwrap();
            is_windows_reserved(stem)
        })

entry
.unpack_in(parent)
.chain_err(|| format!("failed to unpack entry at `{}`", entry_path.display()))?;
entry.unpack_in(parent).chain_err(|| {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be possible to structure this such that the error looks something roughly like this?

error: failed to download ...

Caused by:
  failed to unpack package ...

Caused by:
  failed to unpack entry at '{PATH}'

Caused by:
  '{PATH}' appears to contain a reserved windows path, it cannot be extracted on Windows

Caused by:
  ... More details from tar

So that the windows note is a separate item in the cause chain. You'll need to use let mut result = … to be able to conditionally chain the error, then result = result.chain_err(|| …); inside the condition.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you have an example of this kind of error chaining in the codebase?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, but I think it would look something like this:

let mut result = entry.unpack_in(parent).map_err(anyhow::Error::from);
if cfg!(windows) && restricted_names::is_windows_reserved_path(&entry_path) {
    result = result.chain_err(|| {
        format!(
            "`{}` appears to contain a reserved windows path, \
            it cannot be extracted on Windows",
            entry_path.display()
        )
    });
}
result.chain_err(|| format!("failed to unpack entry at `{}`", entry_path.display()))?;

.chain_err(|| format!("failed to unpack entry at `{}`", entry_path.display()))?;
entry.unpack_in(parent).chain_err(|| {
if cfg!(windows) {
if restricted_names::is_windows_reserved_path(entry_path.as_path()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I usually use deref to convert to a Path, so entry_path.as_path() can be &entry_path.

entry.unpack_in(parent).chain_err(|| {
if cfg!(windows) {
if restricted_names::is_windows_reserved_path(entry_path.as_path()) {
format!(
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't have any effect, since format! just evaluates to a string, it doesn't return from the closure.

@hbina
Copy link
Contributor Author

hbina commented Apr 23, 2020

Thanks for all the comments c: I will take a look at it later today.

@hbina
Copy link
Contributor Author

hbina commented Apr 23, 2020

So how do I write the test for this? I have this

#[cargo_test]
fn reserved_windows_name() {
    Package::new("aux", "1.0.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [project]
            name = "foo"
            version = "0.0.1"
            authors = []
            license = "MIT"
            description = "foo"

            [dependencies]
            aux = "1.0.0"
        "#,
        )
        .file("src/main.rs", "extern crate aux;\nfn main() {  }")
        .build();
    p.cargo("package").run();
}

But this panics with in Windows.

failures:

---- package::reserved_windows_name stdout ----
thread 'package::reserved_windows_name' panicked at 'fs::create_dir_all(dst.parent().unwrap()) failed with The directory name is invalid. (os error 267)', crates\cargo-test-support\src\registry.rs:512:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    package::reserved_windows_name

test result: FAILED. 1802 passed; 1 failed; 3 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test testsuite'

@ehuss
Copy link
Contributor

ehuss commented Apr 23, 2020

You'll want to create a package with a normal name (like bar), with a restricted file, like this:

Package::new("bar", "1.0.0")
    .file("src/lib.rs", "pub mod aux;")
    .file("src/aux.rs", "")
    .publish();

@hbina hbina marked this pull request as ready for review April 24, 2020 19:04
@bors
Copy link
Collaborator

bors commented Apr 24, 2020

☔ The latest upstream changes (presumably #8095) made this pull request unmergeable. Please resolve the merge conflicts.

@ehuss ehuss force-pushed the error_on_illegal_in_windows branch from bfaaa0b to 2c67111 Compare April 26, 2020 13:14
@ehuss
Copy link
Contributor

ehuss commented Apr 26, 2020

Looks great, thanks!
@bors r+

@bors
Copy link
Collaborator

bors commented Apr 26, 2020

📌 Commit 2c67111 has been approved by ehuss

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 26, 2020
@bors
Copy link
Collaborator

bors commented Apr 26, 2020

⌛ Testing commit 2c67111 with merge 4845c033736c43fbc4919cee24ac3884c9b7726c...

@bors
Copy link
Collaborator

bors commented Apr 26, 2020

💔 Test failed - checks-azure

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Apr 26, 2020
@ehuss
Copy link
Contributor

ehuss commented Apr 26, 2020

@bors retry
flaky test #8162

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 26, 2020
@bors
Copy link
Collaborator

bors commented Apr 26, 2020

⌛ Testing commit 2c67111 with merge 11f329d...

@bors
Copy link
Collaborator

bors commented Apr 26, 2020

☀️ Test successful - checks-azure
Approved by: ehuss
Pushing 11f329d to master...

bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 28, 2020
Update cargo

11 commits in 8751eb3010d4cdb5329b5a6bd2b6d765c95b0dca..90931d9b31e8b854522fed00916504a3ac6d8619
2020-04-21 18:04:35 +0000 to 2020-04-28 01:56:59 +0000
- Use associated constants directly on primitive types instead of modules (rust-lang/cargo#8077)
- Clear `RUSTDOCFLAGS` before running tests (rust-lang/cargo#8168)
- Fix warning for `resolve` mismatch in workspace. (rust-lang/cargo#8169)
- Fix flaky linking_interrupted test. (rust-lang/cargo#8162)
- Fixed some unnecessary borrows and clones. (rust-lang/cargo#8146)
- Added warning when using restricted names in Windows. (rust-lang/cargo#8136)
- Add changelog about dylib uplift. (rust-lang/cargo#8161)
- Mention that cargo_metadata can parse json messages (rust-lang/cargo#8158)
- Re-enable rustc-info-cache test again (rust-lang/cargo#8155)
- Updates to path source walking. (rust-lang/cargo#8095)
- Bump to 0.46.0, update changelog (rust-lang/cargo#8153)
@ehuss ehuss added this to the 1.45.0 milestone Feb 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants