Skip to content

Commit 8a8ef26

Browse files
committed
proc_macro: Validate tokens coming from the compiler again
1 parent 4a38408 commit 8a8ef26

File tree

2 files changed

+56
-72
lines changed

2 files changed

+56
-72
lines changed

src/libproc_macro/lib.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -729,11 +729,6 @@ impl Punct {
729729
/// which can be further configured with the `set_span` method below.
730730
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
731731
pub fn new(ch: char, spacing: Spacing) -> Punct {
732-
const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^',
733-
'&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\''];
734-
if !LEGAL_CHARS.contains(&ch) {
735-
panic!("unsupported character `{:?}`", ch)
736-
}
737732
Punct(bridge::client::Punct::new(ch, spacing))
738733
}
739734

@@ -800,16 +795,6 @@ impl fmt::Debug for Punct {
800795
pub struct Ident(bridge::client::Ident);
801796

802797
impl Ident {
803-
fn is_valid(string: &str) -> bool {
804-
let mut chars = string.chars();
805-
if let Some(start) = chars.next() {
806-
(start == '_' || start.is_xid_start())
807-
&& chars.all(|cont| cont == '_' || cont.is_xid_continue())
808-
} else {
809-
false
810-
}
811-
}
812-
813798
/// Creates a new `Ident` with the given `string` as well as the specified
814799
/// `span`.
815800
/// The `string` argument must be a valid identifier permitted by the
@@ -831,18 +816,12 @@ impl Ident {
831816
/// tokens, requires a `Span` to be specified at construction.
832817
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
833818
pub fn new(string: &str, span: Span) -> Ident {
834-
if !Ident::is_valid(string) {
835-
panic!("`{:?}` is not a valid identifier", string)
836-
}
837819
Ident(bridge::client::Ident::new(string, span.0, false))
838820
}
839821

840822
/// Same as `Ident::new`, but creates a raw identifier (`r#ident`).
841823
#[unstable(feature = "proc_macro_raw_ident", issue = "54723")]
842824
pub fn new_raw(string: &str, span: Span) -> Ident {
843-
if !Ident::is_valid(string) {
844-
panic!("`{:?}` is not a valid identifier", string)
845-
}
846825
Ident(bridge::client::Ident::new(string, span.0, true))
847826
}
848827

src/libsyntax_ext/proc_macro_server.rs

Lines changed: 56 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -81,29 +81,23 @@ impl FromInternal<(TokenStream, &'_ ParseSess, &'_ mut Vec<Self>)>
8181
$($field $(: $value)*,)*
8282
span,
8383
})
84-
)
84+
);
85+
($ty:ident::$method:ident($($value:expr),*)) => (
86+
TokenTree::$ty(self::$ty::$method($($value,)* span))
87+
);
8588
}
8689
macro_rules! op {
8790
($a:expr) => {
88-
tt!(Punct { ch: $a, joint })
91+
tt!(Punct::new($a, joint))
8992
};
9093
($a:expr, $b:expr) => {{
91-
stack.push(tt!(Punct { ch: $b, joint }));
92-
tt!(Punct {
93-
ch: $a,
94-
joint: true
95-
})
94+
stack.push(tt!(Punct::new($b, joint)));
95+
tt!(Punct::new($a, true))
9696
}};
9797
($a:expr, $b:expr, $c:expr) => {{
98-
stack.push(tt!(Punct { ch: $c, joint }));
99-
stack.push(tt!(Punct {
100-
ch: $b,
101-
joint: true
102-
}));
103-
tt!(Punct {
104-
ch: $a,
105-
joint: true
106-
})
98+
stack.push(tt!(Punct::new($c, joint)));
99+
stack.push(tt!(Punct::new($b, true)));
100+
tt!(Punct::new($a, true))
107101
}};
108102
}
109103

@@ -156,20 +150,11 @@ impl FromInternal<(TokenStream, &'_ ParseSess, &'_ mut Vec<Self>)>
156150
Question => op!('?'),
157151
SingleQuote => op!('\''),
158152

159-
Ident(ident, is_raw) => tt!(Ident {
160-
sym: ident.name,
161-
is_raw
162-
}),
153+
Ident(ident, is_raw) => tt!(Ident::new(ident.name, is_raw)),
163154
Lifetime(ident) => {
164155
let ident = ident.without_first_quote();
165-
stack.push(tt!(Ident {
166-
sym: ident.name,
167-
is_raw: false
168-
}));
169-
tt!(Punct {
170-
ch: '\'',
171-
joint: true
172-
})
156+
stack.push(tt!(Ident::new(ident.name, false)));
157+
tt!(Punct::new('\'', true))
173158
}
174159
Literal(lit, suffix) => tt!(Literal { lit, suffix }),
175160
DocComment(c) => {
@@ -193,15 +178,9 @@ impl FromInternal<(TokenStream, &'_ ParseSess, &'_ mut Vec<Self>)>
193178
span: DelimSpan::from_single(span),
194179
}));
195180
if style == ast::AttrStyle::Inner {
196-
stack.push(tt!(Punct {
197-
ch: '!',
198-
joint: false
199-
}));
181+
stack.push(tt!(Punct::new('!', false)));
200182
}
201-
tt!(Punct {
202-
ch: '#',
203-
joint: false
204-
})
183+
tt!(Punct::new('#', false))
205184
}
206185

207186
Interpolated(_) => {
@@ -237,7 +216,7 @@ impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
237216
)
238217
.into();
239218
}
240-
TokenTree::Ident(self::Ident { sym, span, is_raw }) => {
219+
TokenTree::Ident(self::Ident { sym, is_raw, span }) => {
241220
let token = Ident(ast::Ident::new(sym, span), is_raw);
242221
return tokenstream::TokenTree::Token(span, token).into();
243222
}
@@ -338,11 +317,48 @@ pub struct Punct {
338317
span: Span,
339318
}
340319

320+
impl Punct {
321+
fn new(ch: char, joint: bool, span: Span) -> Punct {
322+
const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^',
323+
'&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\''];
324+
if !LEGAL_CHARS.contains(&ch) {
325+
panic!("unsupported character `{:?}`", ch)
326+
}
327+
Punct { ch, joint, span }
328+
}
329+
}
330+
341331
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
342332
pub struct Ident {
343333
sym: Symbol,
344-
span: Span,
345334
is_raw: bool,
335+
span: Span,
336+
}
337+
338+
impl Ident {
339+
fn is_valid(string: &str) -> bool {
340+
let mut chars = string.chars();
341+
if let Some(start) = chars.next() {
342+
(start == '_' || start.is_xid_start())
343+
&& chars.all(|cont| cont == '_' || cont.is_xid_continue())
344+
} else {
345+
false
346+
}
347+
}
348+
fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident {
349+
let string = sym.as_str().get();
350+
if !Self::is_valid(string) {
351+
panic!("`{:?}` is not a valid identifier", string)
352+
}
353+
if is_raw {
354+
let normalized_sym = Symbol::intern(string);
355+
if normalized_sym == keywords::Underscore.name() ||
356+
ast::Ident::with_empty_ctxt(normalized_sym).is_path_segment_keyword() {
357+
panic!("`{:?}` is not a valid raw identifier", string)
358+
}
359+
}
360+
Ident { sym, is_raw, span }
361+
}
346362
}
347363

348364
// FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
@@ -492,11 +508,7 @@ impl server::Group for Rustc<'_> {
492508

493509
impl server::Punct for Rustc<'_> {
494510
fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
495-
Punct {
496-
ch,
497-
joint: spacing == Spacing::Joint,
498-
span: server::Span::call_site(self),
499-
}
511+
Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self))
500512
}
501513
fn as_char(&mut self, punct: Self::Punct) -> char {
502514
punct.ch
@@ -518,14 +530,7 @@ impl server::Punct for Rustc<'_> {
518530

519531
impl server::Ident for Rustc<'_> {
520532
fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
521-
let sym = Symbol::intern(string);
522-
if is_raw
523-
&& (sym == keywords::Underscore.name()
524-
|| ast::Ident::with_empty_ctxt(sym).is_path_segment_keyword())
525-
{
526-
panic!("`{:?}` is not a valid raw identifier", string)
527-
}
528-
Ident { sym, span, is_raw }
533+
Ident::new(Symbol::intern(string), is_raw, span)
529534
}
530535
fn span(&mut self, ident: Self::Ident) -> Self::Span {
531536
ident.span

0 commit comments

Comments
 (0)