Skip to content

Commit a0c5e6b

Browse files
authored
Rollup merge of #146211 - Urgau:cfg-disallow-shebang, r=fmease
Disallow shebang in `--cfg` and `--check-cfg` arguments This PR is similar to #146130, where we disallowed frontmatter in `--cfg` and `--check-cfg` arguments. While fixing the other one we also discovered that shebang `#!/usr/bin/shebang` are currently also allowed in `--cfg` and `--check-cfg` arguments. Allowing shebang in them (which are just ignored) was never intended, this PR fixes that by not stripping shebang for `--cfg` and `--check-cfg` arguments. This is technically a breaking-change, although I don't expect anyone to actually rely on this unintended behavior. Fixes #146130 (comment) r? fmease
2 parents bc0dfaa + d224d3a commit a0c5e6b

File tree

7 files changed

+75
-29
lines changed

7 files changed

+75
-29
lines changed

compiler/rustc_parse/src/lexer/mod.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,44 @@ pub(crate) struct UnmatchedDelim {
4444
pub candidate_span: Option<Span>,
4545
}
4646

47+
/// Which tokens should be stripped before lexing the tokens.
48+
pub(crate) enum StripTokens {
49+
/// Strip both shebang and frontmatter.
50+
ShebangAndFrontmatter,
51+
/// Strip the shebang but not frontmatter.
52+
///
53+
/// That means that char sequences looking like frontmatter are simply
54+
/// interpreted as regular Rust lexemes.
55+
Shebang,
56+
/// Strip nothing.
57+
///
58+
/// In other words, char sequences looking like a shebang or frontmatter
59+
/// are simply interpreted as regular Rust lexemes.
60+
Nothing,
61+
}
62+
4763
pub(crate) fn lex_token_trees<'psess, 'src>(
4864
psess: &'psess ParseSess,
4965
mut src: &'src str,
5066
mut start_pos: BytePos,
5167
override_span: Option<Span>,
52-
frontmatter_allowed: FrontmatterAllowed,
68+
strip_tokens: StripTokens,
5369
) -> Result<TokenStream, Vec<Diag<'psess>>> {
54-
// Skip `#!`, if present.
55-
if let Some(shebang_len) = rustc_lexer::strip_shebang(src) {
56-
src = &src[shebang_len..];
57-
start_pos = start_pos + BytePos::from_usize(shebang_len);
70+
match strip_tokens {
71+
StripTokens::Shebang | StripTokens::ShebangAndFrontmatter => {
72+
if let Some(shebang_len) = rustc_lexer::strip_shebang(src) {
73+
src = &src[shebang_len..];
74+
start_pos = start_pos + BytePos::from_usize(shebang_len);
75+
}
76+
}
77+
StripTokens::Nothing => {}
5878
}
5979

80+
let frontmatter_allowed = match strip_tokens {
81+
StripTokens::ShebangAndFrontmatter => FrontmatterAllowed::Yes,
82+
StripTokens::Shebang | StripTokens::Nothing => FrontmatterAllowed::No,
83+
};
84+
6085
let cursor = Cursor::new(src, frontmatter_allowed);
6186
let mut lexer = Lexer {
6287
psess,

compiler/rustc_parse/src/lib.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream};
2121
use rustc_ast::{AttrItem, Attribute, MetaItemInner, token};
2222
use rustc_ast_pretty::pprust;
2323
use rustc_errors::{Diag, EmissionGuarantee, FatalError, PResult, pluralize};
24-
use rustc_lexer::FrontmatterAllowed;
2524
use rustc_session::parse::ParseSess;
2625
use rustc_span::source_map::SourceMap;
2726
use rustc_span::{FileName, SourceFile, Span};
@@ -34,6 +33,8 @@ pub mod parser;
3433
use parser::Parser;
3534
use rustc_ast::token::Delimiter;
3635

36+
use crate::lexer::StripTokens;
37+
3738
pub mod lexer;
3839

3940
mod errors;
@@ -62,10 +63,10 @@ pub fn new_parser_from_source_str(
6263
source: String,
6364
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
6465
let source_file = psess.source_map().new_source_file(name, source);
65-
new_parser_from_source_file(psess, source_file, FrontmatterAllowed::Yes)
66+
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter)
6667
}
6768

68-
/// Creates a new parser from a simple (no frontmatter) source string.
69+
/// Creates a new parser from a simple (no shebang, no frontmatter) source string.
6970
///
7071
/// On failure, the errors must be consumed via `unwrap_or_emit_fatal`, `emit`, `cancel`,
7172
/// etc., otherwise a panic will occur when they are dropped.
@@ -75,7 +76,7 @@ pub fn new_parser_from_simple_source_str(
7576
source: String,
7677
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
7778
let source_file = psess.source_map().new_source_file(name, source);
78-
new_parser_from_source_file(psess, source_file, FrontmatterAllowed::No)
79+
new_parser_from_source_file(psess, source_file, StripTokens::Nothing)
7980
}
8081

8182
/// Creates a new parser from a filename. On failure, the errors must be consumed via
@@ -109,7 +110,7 @@ pub fn new_parser_from_file<'a>(
109110
}
110111
err.emit();
111112
});
112-
new_parser_from_source_file(psess, source_file, FrontmatterAllowed::Yes)
113+
new_parser_from_source_file(psess, source_file, StripTokens::ShebangAndFrontmatter)
113114
}
114115

115116
pub fn utf8_error<E: EmissionGuarantee>(
@@ -160,10 +161,10 @@ pub fn utf8_error<E: EmissionGuarantee>(
160161
fn new_parser_from_source_file(
161162
psess: &ParseSess,
162163
source_file: Arc<SourceFile>,
163-
frontmatter_allowed: FrontmatterAllowed,
164+
strip_tokens: StripTokens,
164165
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
165166
let end_pos = source_file.end_position();
166-
let stream = source_file_to_stream(psess, source_file, None, frontmatter_allowed)?;
167+
let stream = source_file_to_stream(psess, source_file, None, strip_tokens)?;
167168
let mut parser = Parser::new(psess, stream, None);
168169
if parser.token == token::Eof {
169170
parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None);
@@ -179,8 +180,8 @@ pub fn source_str_to_stream(
179180
) -> Result<TokenStream, Vec<Diag<'_>>> {
180181
let source_file = psess.source_map().new_source_file(name, source);
181182
// used mainly for `proc_macro` and the likes, not for our parsing purposes, so don't parse
182-
// frontmatters as frontmatters.
183-
source_file_to_stream(psess, source_file, override_span, FrontmatterAllowed::No)
183+
// frontmatters as frontmatters, but for compatibility reason still strip the shebang
184+
source_file_to_stream(psess, source_file, override_span, StripTokens::Shebang)
184185
}
185186

186187
/// Given a source file, produces a sequence of token trees. Returns any buffered errors from
@@ -189,7 +190,7 @@ fn source_file_to_stream<'psess>(
189190
psess: &'psess ParseSess,
190191
source_file: Arc<SourceFile>,
191192
override_span: Option<Span>,
192-
frontmatter_allowed: FrontmatterAllowed,
193+
strip_tokens: StripTokens,
193194
) -> Result<TokenStream, Vec<Diag<'psess>>> {
194195
let src = source_file.src.as_ref().unwrap_or_else(|| {
195196
psess.dcx().bug(format!(
@@ -198,13 +199,7 @@ fn source_file_to_stream<'psess>(
198199
));
199200
});
200201

201-
lexer::lex_token_trees(
202-
psess,
203-
src.as_str(),
204-
source_file.start_pos,
205-
override_span,
206-
frontmatter_allowed,
207-
)
202+
lexer::lex_token_trees(psess, src.as_str(), source_file.start_pos, override_span, strip_tokens)
208203
}
209204

210205
/// Runs the given subparser `f` on the tokens of the given `attr`'s item.
File renamed without changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
error: invalid `--cfg` argument: `#!/usr/bin/shebang
2+
key` (expected `key` or `key="value"`)
3+
File renamed without changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
error: invalid `--check-cfg` argument: `#!/usr/bin/shebang
2+
cfg(key)`
3+
|
4+
= note: expected `cfg(name, values("value1", "value2", ... "valueN"))`
5+
= note: visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details
6+
Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
use run_make_support::{cwd, diff, rustc};
22

3-
fn test_and_compare(flag: &str, val: &str) {
3+
fn test_and_compare(test_name: &str, flag: &str, val: &str) {
44
let mut cmd = rustc();
55

6-
let output =
7-
cmd.input("").arg("--crate-type=lib").arg(&format!("--{flag}")).arg(val).run_fail();
6+
let output = cmd.input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail();
87

98
assert_eq!(output.stdout_utf8(), "");
109
diff()
11-
.expected_file(format!("{flag}.stderr"))
12-
.actual_text("output", output.stderr_utf8())
10+
.expected_file(format!("{test_name}.stderr"))
11+
.actual_text("stderr", output.stderr_utf8())
1312
.run();
1413
}
1514

1615
fn main() {
1716
// Verify that frontmatter isn't allowed in `--cfg` arguments.
1817
// https://github.com/rust-lang/rust/issues/146130
1918
test_and_compare(
20-
"cfg",
19+
"cfg-frontmatter",
20+
"--cfg",
2121
r#"---
2222
---
2323
key"#,
@@ -26,9 +26,26 @@ key"#,
2626
// Verify that frontmatter isn't allowed in `--check-cfg` arguments.
2727
// https://github.com/rust-lang/rust/issues/146130
2828
test_and_compare(
29-
"check-cfg",
29+
"check-cfg-frontmatter",
30+
"--check-cfg",
3031
r#"---
3132
---
33+
cfg(key)"#,
34+
);
35+
36+
// Verify that shebang isn't allowed in `--cfg` arguments.
37+
test_and_compare(
38+
"cfg-shebang",
39+
"--cfg",
40+
r#"#!/usr/bin/shebang
41+
key"#,
42+
);
43+
44+
// Verify that shebang isn't allowed in `--check-cfg` arguments.
45+
test_and_compare(
46+
"check-cfg-shebang",
47+
"--check-cfg",
48+
r#"#!/usr/bin/shebang
3249
cfg(key)"#,
3350
);
3451
}

0 commit comments

Comments
 (0)