rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.32k stars 12.46k forks source link

Library builds fail when path contains a percent char (%) #79567

Open nospam3089 opened 3 years ago

nospam3089 commented 3 years ago

I have read CONTRIBUTING.md as well as the contributing guidelines. Searching for '%' and 'percent' does not seem to lead to any relevant existing issues. From my understanding of man cargo, man cargo-build and The Cargo Book, they do not make it obvious that restrictions like these should be imposed. Neither does man rustc seem to state that the %-character should be treated special in any way.

I tried this code:

mkdir -p '%/foo'
cd '%/foo'
cargo init --lib
cargo build
   Compiling foo v0.1.0 (/%/foo)
     Running `rustc --crate-name foo --edition=2018 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=bed926cd50182e06 -C extra-filename=-bed926cd50182e06 --out-dir '/%/foo/target/debug/deps' -C 'incremental=/%/foo/target/debug/incremental' -L 'dependency=/%/foo/target/debug/deps'`
error: failed to build archive: No such file or directory

error: aborting due to previous error

error: could not compile `foo`.

Caused by:
  process didn't exit successfully: `rustc --crate-name foo --edition=2018 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=bed926cd50182e06 -C extra-filename=-bed926cd50182e06 --out-dir '/%/foo/target/debug/deps' -C 'incremental=/%/foo/target/debug/incremental' -L 'dependency=/%/foo/target/debug/deps'` (exit code: 1)
% 

I expected to see this happen: A successful build, comparable to if doing

mkdir -p '%/bar'
cd '%/bar'
cargo init --bin
cargo build --verbose
cargo build
   Compiling bar v0.1.0 (/%/bar)
    Finished dev [unoptimized + debuginfo] target(s) in 0.65s
% 

Instead, this happened: The build fails, whenever the actual directory or any parent contains at least one percent character. I can only speculate on why, but it would be likely to assume some tool upon which rustc depends treats percent characters as special, and that rustc is missing some escaping which should be performed.

For what its worth, this was found due to it causing real issues with our specific use of a fairly common continuous integration system. We can work around it, but it would be great if the need for such mitigation could be removed.

Meta

This applies to 1.47.0, 1.48.0 as well as 1.50.0-nightly (bfca1cd22 2020-11-24), on at least linux and illumos.

uname -srvmpio; rustc --version --verbose:

SunOS 5.11 omnios-r151030-58b4169e77 i86pc i386 i86pc illumos
rustc 1.48.0
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-unknown-illumos
release: 1.48.0
LLVM version: 11.0

uname -srvmpio; rustc +nightly --version --verbose:

Linux 5.9.0-1-amd64 #1 SMP Debian 5.9.1-1 (2020-10-17) x86_64 unknown unknown GNU/Linux
cargo +nightly --verbose --version
cargo 1.50.0-nightly (bfca1cd22 2020-11-24)
release: 1.50.0
commit-hash: bfca1cd22bf514d5f2b6c1089b0ded0ba7dfaa6e
commit-date: 2020-11-24

Backtrace

``` N/A Build fails. ```

jyn514 commented 3 years ago

FWIW this works for me on linux, so I'd expect this to be specific to SunOS.

camelid commented 3 years ago

This applies to 1.47.0, 1.48.0 as well as 1.50.0-nightly (bfca1cd22 2020-11-24), on at least linux and illumos.

@jyn514 ^

Perhaps a different distro is the problem?

camelid commented 3 years ago

Can confirm this occurs on macOS too:

     Created library package
   Compiling foo v0.1.0 (/Users/user/%/foo)
error: failed to build archive: No such file or directory

error: aborting due to previous error

error: could not compile `foo`
camelid commented 3 years ago

Looks like it occurs in rustc_codegen_llvm:

https://github.com/rust-lang/rust/blob/b7ebc6b0c1ba3c27ebb17c0b496ece778ef11e18/compiler/rustc_codegen_llvm/src/back/archive.rs#L173-L175

camelid commented 3 years ago

Might be an LLVM bug.

camelid commented 3 years ago

@rustbot ping llvm

rustbot commented 3 years ago

Hey LLVM ICE-breakers! This bug has been identified as a good "LLVM ICE-breaking candidate". In case it's useful, here are some instructions for tackling these sorts of bugs. Maybe take a look? Thanks! <3

cc @camelid @comex @cuviper @DutchGhost @hdhoang @heyrutvik @higuoxing @JOE1994 @jryans @mmilenko @nagisa @nikic @Noah-Kennedy @SiavoshZarrasvand @spastorino @vertexclique

kkuehlz commented 3 years ago

@camelid I think the reason is because llvm::writeArchive(..) creates a temp file as follows:

Expected<sys::fs::TempFile> Temp =                                                                                         
      sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a");                                                        

It ends up hitting this code path. The % in the file path gets formatted with a random character. It looks like it's common in their tree to call sys::fs::TempFile::create(Prefix + ".temp-archive-%%%%%%%.a"), and Prefix is assumed not to contain any % characters. Seems like something that should be fixed upstream. mktemp has a similar API but only replaces the Xs in the final component. In the LLVM tree, the intended replacements seem to happen if the string of %s are the final characters, or if they are between the final - and the file extension.

I created a report upstream https://bugs.llvm.org/show_bug.cgi?id=49750