about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-22 19:57:07 +0000
committerbors <bors@rust-lang.org>2023-09-22 19:57:07 +0000
commitaadb5718dd9a2f4b9c64893baedfe1f5991d6bbd (patch)
tree9e9bcde725b945801aa3cf91b23d4d22899f03f0
parent959b2c703d45f06962da3afa086bdda70d42efcf (diff)
parent8d81d5a909551631b51177f976f68ac02dcafd11 (diff)
downloadrust-aadb5718dd9a2f4b9c64893baedfe1f5991d6bbd.tar.gz
rust-aadb5718dd9a2f4b9c64893baedfe1f5991d6bbd.zip
Auto merge of #116001 - fmease:validate-crate-name-extern-cli-opt, r=est31
[breaking change] Validate crate name in `--extern` [MCP 650]

Reject non-ASCII-identifier crate names passed to the CLI option `--extern` (`rustc`, `rustdoc`).
Implements [MCP 650](https://github.com/rust-lang/compiler-team/issues/650) (except that we only allow ASCII identifiers not arbitrary Rust identifiers).
Fixes #113035.

[As mentioned on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Disallow.20non-identifier-valid.20--extern.20cr.E2.80.A6.20compiler-team.23650/near/376826988), doing a crater run probably doesn't make sense since it wouldn't yield anything. Most users don't interact with `rustc` directly but only ever through Cargo which always passes a valid crate name to `--extern` when it invokes `rustc` and `rustdoc`. In any case, the user wouldn't be able to use such a crate name in the source code anyway.

Note that I'm not using [`rustc_session::output::validate_crate_name`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/output/fn.validate_crate_name.html) (used for `--crate-name` and `#![crate_name]`) since the latter doesn't reject non-ASCII crate names and ones that start with a digit.

As an aside, I've also thought about getting rid of `validate_crate_name` entirely in a separate PR (with another MCP) in favor of `is_ascii_ident` to reject more weird `--crate-name`s, `#![crate_name]`s and file names but I think that would lead to a lot of actual breakage, namely because of file names starting with a digit. In `tests/ui` 9 tests would be impacted for example.

CC `@estebank`
r? `@est31`
-rw-r--r--compiler/rustc_session/src/config.rs13
-rw-r--r--compiler/rustc_session/src/session.rs9
-rw-r--r--compiler/rustc_session/src/utils.rs9
-rw-r--r--tests/run-make/incr-foreign-head-span/Makefile2
-rw-r--r--tests/ui/extern-flag/invalid-crate-name-dashed.rs10
-rw-r--r--tests/ui/extern-flag/invalid-crate-name-dashed.stderr4
-rw-r--r--tests/ui/extern-flag/invalid-crate-name-non-ascii.rs4
-rw-r--r--tests/ui/extern-flag/invalid-crate-name-non-ascii.stderr2
-rw-r--r--tests/ui/extern-flag/invalid-crate-name.rs4
-rw-r--r--tests/ui/extern-flag/invalid-crate-name.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs6
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs (renamed from tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.rs)0
-rw-r--r--tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr (renamed from tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr)2
-rw-r--r--tests/ui/rust-2018/trait-import-suggestions.rs2
15 files changed, 60 insertions, 17 deletions
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 956ae149e55..d29ab02c1a6 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2475,6 +2475,19 @@ pub fn parse_externs(
             Some((opts, name)) => (Some(opts), name.to_string()),
         };
 
+        if !crate::utils::is_ascii_ident(&name) {
+            let mut error = handler.early_struct_error(format!(
+                "crate name `{name}` passed to `--extern` is not a valid ASCII identifier"
+            ));
+            let adjusted_name = name.replace("-", "_");
+            if crate::utils::is_ascii_ident(&adjusted_name) {
+                error.help(format!(
+                    "consider replacing the dashes with underscores: `{adjusted_name}`"
+                ));
+            }
+            error.emit();
+        }
+
         let path = path.map(|p| CanonicalizedPath::new(p));
 
         let entry = externs.entry(name.to_owned());
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 86f4e7b48da..b484978eed2 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1726,6 +1726,15 @@ impl EarlyErrorHandler {
 
     #[allow(rustc::untranslatable_diagnostic)]
     #[allow(rustc::diagnostic_outside_of_impl)]
+    pub(crate) fn early_struct_error(
+        &self,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> DiagnosticBuilder<'_, !> {
+        self.handler.struct_fatal(msg)
+    }
+
+    #[allow(rustc::untranslatable_diagnostic)]
+    #[allow(rustc::diagnostic_outside_of_impl)]
     pub fn early_warn(&self, msg: impl Into<DiagnosticMessage>) {
         self.handler.struct_warn(msg).emit()
     }
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index f76c69af526..aea7c6c2842 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -158,3 +158,12 @@ pub fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
 
     if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
 }
+
+pub(crate) fn is_ascii_ident(string: &str) -> bool {
+    let mut chars = string.chars();
+    if let Some(start) = chars.next() && (start.is_ascii_alphabetic() || start == '_') {
+        chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
+    } else {
+        false
+    }
+}
diff --git a/tests/run-make/incr-foreign-head-span/Makefile b/tests/run-make/incr-foreign-head-span/Makefile
index 9d6102cdd72..9be4b0f601c 100644
--- a/tests/run-make/incr-foreign-head-span/Makefile
+++ b/tests/run-make/incr-foreign-head-span/Makefile
@@ -15,7 +15,7 @@ INCR=$(TMPDIR)/incr
 all:
 	cp first_crate.rs second_crate.rs $(TMPDIR)
 	$(RUSTC) $(TMPDIR)/first_crate.rs  -C incremental=$(INCR) --target $(TARGET) --crate-type lib
-	$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET)  --extern first-crate=$(TMPDIR) --crate-type lib
+	$(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET)  --extern first_crate=$(TMPDIR)/libfirst_crate.rlib --crate-type lib
 	rm $(TMPDIR)/first_crate.rs
 	$(RUSTC) $(TMPDIR)/second_crate.rs  -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib
 
diff --git a/tests/ui/extern-flag/invalid-crate-name-dashed.rs b/tests/ui/extern-flag/invalid-crate-name-dashed.rs
new file mode 100644
index 00000000000..7f351e48b6f
--- /dev/null
+++ b/tests/ui/extern-flag/invalid-crate-name-dashed.rs
@@ -0,0 +1,10 @@
+// compile-flags: --extern=my-awesome-library=libawesome.rlib
+// error-pattern: crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier
+// error-pattern: consider replacing the dashes with underscores: `my_awesome_library`
+
+// In a sense, this is a regression test for issue #113035. We no longer suggest
+// `pub use my-awesome-library::*;` (sic!) as we outright ban this crate name.
+
+pub use my_awesome_library::*;
+
+fn main() {}
diff --git a/tests/ui/extern-flag/invalid-crate-name-dashed.stderr b/tests/ui/extern-flag/invalid-crate-name-dashed.stderr
new file mode 100644
index 00000000000..5da1c4bb20a
--- /dev/null
+++ b/tests/ui/extern-flag/invalid-crate-name-dashed.stderr
@@ -0,0 +1,4 @@
+error: crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier
+  |
+  = help: consider replacing the dashes with underscores: `my_awesome_library`
+
diff --git a/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs b/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs
new file mode 100644
index 00000000000..ec4a85820d1
--- /dev/null
+++ b/tests/ui/extern-flag/invalid-crate-name-non-ascii.rs
@@ -0,0 +1,4 @@
+// compile-flags: --extern čɍαţē=libnon_ascii.rlib
+// error-pattern: crate name `čɍαţē` passed to `--extern` is not a valid ASCII identifier
+
+fn main() {}
diff --git a/tests/ui/extern-flag/invalid-crate-name-non-ascii.stderr b/tests/ui/extern-flag/invalid-crate-name-non-ascii.stderr
new file mode 100644
index 00000000000..6b38dcd01e0
--- /dev/null
+++ b/tests/ui/extern-flag/invalid-crate-name-non-ascii.stderr
@@ -0,0 +1,2 @@
+error: crate name `čɍαţē` passed to `--extern` is not a valid ASCII identifier
+
diff --git a/tests/ui/extern-flag/invalid-crate-name.rs b/tests/ui/extern-flag/invalid-crate-name.rs
new file mode 100644
index 00000000000..a26b5dd4635
--- /dev/null
+++ b/tests/ui/extern-flag/invalid-crate-name.rs
@@ -0,0 +1,4 @@
+// compile-flags: --extern=?#1%$
+// error-pattern: crate name `?#1%$` passed to `--extern` is not a valid ASCII identifier
+
+fn main() {}
diff --git a/tests/ui/extern-flag/invalid-crate-name.stderr b/tests/ui/extern-flag/invalid-crate-name.stderr
new file mode 100644
index 00000000000..e2f83160db9
--- /dev/null
+++ b/tests/ui/extern-flag/invalid-crate-name.stderr
@@ -0,0 +1,2 @@
+error: crate name `?#1%$` passed to `--extern` is not a valid ASCII identifier
+
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs
deleted file mode 100644
index f8e033937c6..00000000000
--- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// compile-flags:--extern му_сгате
-// edition:2018
-
-use му_сгате::baz; //~  ERROR cannot load a crate with a non-ascii name `му_сгате`
-
-fn main() {}
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr
deleted file mode 100644
index 05fc4fb22ad..00000000000
--- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-2.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: cannot load a crate with a non-ascii name `му_сгате`
-  --> $DIR/crate_name_nonascii_forbidden-2.rs:4:5
-   |
-LL | use му_сгате::baz;
-   |     ^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs
index c07ba54af40..c07ba54af40 100644
--- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.rs
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.rs
diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr
index a8f3abe599e..5aade17cba5 100644
--- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden-1.stderr
+++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/crate_name_nonascii_forbidden.stderr
@@ -1,5 +1,5 @@
 error: cannot load a crate with a non-ascii name `ьаг`
-  --> $DIR/crate_name_nonascii_forbidden-1.rs:1:1
+  --> $DIR/crate_name_nonascii_forbidden.rs:1:1
    |
 LL | extern crate ьаг;
    | ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2018/trait-import-suggestions.rs b/tests/ui/rust-2018/trait-import-suggestions.rs
index 9c67c3f4b4b..900b3d09334 100644
--- a/tests/ui/rust-2018/trait-import-suggestions.rs
+++ b/tests/ui/rust-2018/trait-import-suggestions.rs
@@ -1,6 +1,6 @@
 // edition:2018
 // aux-build:trait-import-suggestions.rs
-// compile-flags:--extern trait-import-suggestions
+// compile-flags:--extern trait_import_suggestions
 
 mod foo {
     mod foobar {