Skip to content

Commit 8f443eb

Browse files
zerocopy-derive: Fix panic with raw identifiers (#2788)
* zerocopy-derive: Fix panic with raw identifiers Stripped `r#` prefix from identifiers when generating internal field/variant names in `zerocopy-derive`. This prevents panics when using raw identifiers (e.g., `r#type`) in structs or enums. Added regression tests in `zerocopy-derive/tests/struct_known_layout.rs` and `zerocopy-derive/tests/enum_try_from_bytes.rs`. Closes #2234 * zerocopy-derive: Fix panic with raw identifiers Factor out logic to strip `r#` prefix from identifiers into `to_ident_str` helper in `zerocopy-derive/src/ext.rs`. Use this helper in `zerocopy-derive/src/lib.rs` and `zerocopy-derive/src/enum.rs` when generating internal identifiers. This prevents panics when using raw identifiers (e.g., `r#type`) in structs or enums. Added regression tests in `zerocopy-derive/tests/struct_known_layout.rs` and `zerocopy-derive/tests/enum_try_from_bytes.rs`. --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent e69ede3 commit 8f443eb

File tree

5 files changed

+35
-5
lines changed

5 files changed

+35
-5
lines changed

zerocopy-derive/src/enum.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ pub(crate) fn generate_tag_enum(repr: &EnumRepr, data: &DataEnum) -> TokenStream
4343
}
4444

4545
fn tag_ident(variant_ident: &Ident) -> Ident {
46-
Ident::new(&format!("___ZEROCOPY_TAG_{}", variant_ident), variant_ident.span())
46+
let variant_ident_str = crate::ext::to_ident_str(variant_ident);
47+
Ident::new(&format!("___ZEROCOPY_TAG_{}", variant_ident_str), variant_ident.span())
4748
}
4849

4950
/// Generates a constant for the tag associated with each variant of the enum.
@@ -84,7 +85,8 @@ fn generate_tag_consts(data: &DataEnum) -> TokenStream {
8485
}
8586

8687
fn variant_struct_ident(variant_ident: &Ident) -> Ident {
87-
Ident::new(&format!("___ZerocopyVariantStruct_{}", variant_ident), variant_ident.span())
88+
let variant_ident_str = crate::ext::to_ident_str(variant_ident);
89+
Ident::new(&format!("___ZerocopyVariantStruct_{}", variant_ident_str), variant_ident.span())
8890
}
8991

9092
/// Generates variant structs for the given enum variant.
@@ -162,7 +164,8 @@ fn generate_variants_union(generics: &Generics, data: &DataEnum) -> TokenStream
162164

163165
// Field names are prefixed with `__field_` to prevent name collision with
164166
// the `__nonempty` field.
165-
let field_name = Ident::new(&format!("__field_{}", &variant.ident), variant.ident.span());
167+
let field_name_str = crate::ext::to_ident_str(&variant.ident);
168+
let field_name = Ident::new(&format!("__field_{}", field_name_str), variant.ident.span());
166169
let variant_struct_ident = variant_struct_ident(&variant.ident);
167170

168171
Some(quote! {

zerocopy-derive/src/ext.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,12 @@ fn map_fields<'a>(
112112
})
113113
.collect()
114114
}
115+
116+
pub(crate) fn to_ident_str(t: &impl ToString) -> String {
117+
let s = t.to_string();
118+
if let Some(stripped) = s.strip_prefix("r#") {
119+
stripped.to_string()
120+
} else {
121+
s
122+
}
123+
}

zerocopy-derive/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,10 @@ fn derive_known_layout_inner(
318318

319319
// Generate a valid ident for a type-level handle to a field of a
320320
// given `name`.
321-
let field_index =
322-
|name| Ident::new(&format!("__Zerocopy_Field_{}", name), ident.span());
321+
let field_index = |name: &TokenStream| {
322+
let name = to_ident_str(name);
323+
Ident::new(&format!("__Zerocopy_Field_{}", name), ident.span())
324+
};
323325

324326
let field_indices: Vec<_> =
325327
fields.iter().map(|(_vis, name, _ty)| field_index(name)).collect();

zerocopy-derive/tests/enum_try_from_bytes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,3 +642,11 @@ mod issue_2051 {
642642
I32_MUL,
643643
}
644644
}
645+
646+
#[derive(imp::TryFromBytes)]
647+
#[repr(u8)]
648+
enum RawIdentifierVariant {
649+
r#type,
650+
}
651+
652+
util_assert_impl_all!(RawIdentifierVariant: imp::TryFromBytes);

zerocopy-derive/tests/struct_known_layout.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,11 @@ struct Packet<P> {
112112
}
113113

114114
util_assert_impl_all!(Packet<imp::u8>: imp::KnownLayout);
115+
116+
#[derive(imp::KnownLayout)]
117+
#[repr(C)]
118+
struct RawIdentifier {
119+
r#type: u8,
120+
}
121+
122+
util_assert_impl_all!(RawIdentifier: imp::KnownLayout);

0 commit comments

Comments
 (0)