From 805a6adf92ba8da4b6d7ce5ff1def6b53f1f1cb5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 25 Nov 2023 17:13:54 -0800 Subject: [PATCH] Bypass Ident validation on identifiers created by parser --- src/fallback.rs | 38 ++++++++++++++++++++++++-------------- src/parse.rs | 19 +++++++++++++------ src/wrapper.rs | 8 ++++++++ 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/fallback.rs b/src/fallback.rs index b02fd04..408102b 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -755,22 +755,30 @@ pub(crate) struct Ident { } impl Ident { - fn _new(string: &str, raw: bool, span: Span) -> Self { - validate_ident(string, raw); + pub fn new(string: &str, span: Span) -> Self { + validate_ident(string); + Ident::new_unchecked(string, span) + } + pub fn new_unchecked(string: &str, span: Span) -> Self { Ident { sym: string.to_owned(), span, - raw, + raw: false, } } - pub fn new(string: &str, span: Span) -> Self { - Ident::_new(string, false, span) + pub fn new_raw(string: &str, span: Span) -> Self { + validate_ident_raw(string); + Ident::new_raw_unchecked(string, span) } - pub fn new_raw(string: &str, span: Span) -> Self { - Ident::_new(string, true, span) + pub fn new_raw_unchecked(string: &str, span: Span) -> Self { + Ident { + sym: string.to_owned(), + span, + raw: true, + } } pub fn span(&self) -> Span { @@ -790,7 +798,7 @@ pub(crate) fn is_ident_continue(c: char) -> bool { unicode_ident::is_xid_continue(c) } -fn validate_ident(string: &str, raw: bool) { +fn validate_ident(string: &str) { if string.is_empty() { panic!("Ident is not allowed to be empty; use Option"); } @@ -816,14 +824,16 @@ fn validate_ident(string: &str, raw: bool) { if !ident_ok(string) { panic!("{:?} is not a valid Ident", string); } +} - if raw { - match string { - "_" | "super" | "self" | "Self" | "crate" => { - panic!("`r#{}` cannot be a raw identifier", string); - } - _ => {} +fn validate_ident_raw(string: &str) { + validate_ident(string); + + match string { + "_" | "super" | "self" | "Self" | "crate" => { + panic!("`r#{}` cannot be a raw identifier", string); } + _ => {} } } diff --git a/src/parse.rs b/src/parse.rs index 8c3d9b2..07239bc 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,5 +1,5 @@ use crate::fallback::{ - is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream, + self, is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream, TokenStreamBuilder, }; use crate::{Delimiter, Punct, Spacing, TokenTree}; @@ -300,7 +300,10 @@ fn ident_any(input: Cursor) -> PResult { let (rest, sym) = ident_not_raw(rest)?; if !raw { - let ident = crate::Ident::new(sym, crate::Span::call_site()); + let ident = crate::Ident::_new(crate::imp::Ident::new_unchecked( + sym, + fallback::Span::call_site(), + )); return Ok((rest, ident)); } @@ -309,7 +312,10 @@ fn ident_any(input: Cursor) -> PResult { _ => {} } - let ident = crate::Ident::new_raw(sym, crate::Span::call_site()); + let ident = crate::Ident::_new(crate::imp::Ident::new_raw_unchecked( + sym, + fallback::Span::call_site(), + )); Ok((rest, ident)) } @@ -908,12 +914,13 @@ fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult #[cfg(span_locations)] let lo = input.off; let (rest, (comment, inner)) = doc_comment_contents(input)?; - let span = crate::Span::_new_fallback(Span { + let fallback_span = Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: rest.off, - }); + }; + let span = crate::Span::_new_fallback(fallback_span); let mut scan_for_bare_cr = comment; while let Some(cr) = scan_for_bare_cr.find('\r') { @@ -934,7 +941,7 @@ fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult trees.push_token_from_parser(TokenTree::Punct(bang)); } - let doc_ident = crate::Ident::new("doc", span); + let doc_ident = crate::Ident::_new(crate::imp::Ident::new_unchecked("doc", fallback_span)); let mut equal = Punct::new('=', Spacing::Alone); equal.set_span(span); let mut literal = crate::Literal::string(comment); diff --git a/src/wrapper.rs b/src/wrapper.rs index 860b6b7..9bac8d1 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -646,6 +646,10 @@ impl Ident { } } + pub fn new_unchecked(string: &str, span: fallback::Span) -> Self { + Ident::Fallback(fallback::Ident::new_unchecked(string, span)) + } + pub fn new_raw(string: &str, span: Span) -> Self { match span { Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)), @@ -653,6 +657,10 @@ impl Ident { } } + pub fn new_raw_unchecked(string: &str, span: fallback::Span) -> Self { + Ident::Fallback(fallback::Ident::new_raw_unchecked(string, span)) + } + pub fn span(&self) -> Span { match self { Ident::Compiler(t) => Span::Compiler(t.span()),