From 401735a94912e6d0333cbccdbcf5ec75be0cdda2 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sun, 24 Sep 2023 22:48:16 -0500 Subject: [PATCH 1/5] Don't escape objective-c method names --- bindgen/ir/objc.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bindgen/ir/objc.rs b/bindgen/ir/objc.rs index 2ebf38b8ca..e2f3696548 100644 --- a/bindgen/ir/objc.rs +++ b/bindgen/ir/objc.rs @@ -253,9 +253,12 @@ impl ObjCMethod { let split_name: Vec> = self .name .split(':') - .map(|name| { + .enumerate() + .map(|(idx, name)| { if name.is_empty() { None + } else if idx == 0 { + Some(Ident::new(name, Span::call_site())) } else { // Try to parse the current name as an identifier. This might fail if the name // is a keyword, so we try to "r#" to it and parse again, this could also fail From 2b943f294c58f0245868bd259b388b89a9101e49 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sun, 24 Sep 2023 22:55:33 -0500 Subject: [PATCH 2/5] Still escape `crate`, `self`, and the like --- bindgen/ir/objc.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bindgen/ir/objc.rs b/bindgen/ir/objc.rs index e2f3696548..65027d38ae 100644 --- a/bindgen/ir/objc.rs +++ b/bindgen/ir/objc.rs @@ -258,9 +258,19 @@ impl ObjCMethod { if name.is_empty() { None } else if idx == 0 { - Some(Ident::new(name, Span::call_site())) + // Try to parse the method name as an identifier. Having a keyword is ok + // unless it is `crate`, `self`, `super` or `Self`, so we try to add the `_` + // suffix to it and parse it. + Some( + syn::parse_str::(name) + .or_else(|err| { + syn::parse_str::(&format!("{}_", name)) + .map_err(|_| err) + }) + .expect("Invalid identifier"), + ) } else { - // Try to parse the current name as an identifier. This might fail if the name + // Try to parse the current joining name as an identifier. This might fail if the name // is a keyword, so we try to "r#" to it and parse again, this could also fail // if the name is `crate`, `self`, `super` or `Self`, so we try to add the `_` // suffix to it and parse again. If this also fails, we panic with the first From b17e1a52f9ebd2b640eb220ff6542c77496e83b7 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sun, 24 Sep 2023 23:07:14 -0500 Subject: [PATCH 3/5] Don't escape keywords if they are method names --- bindgen/ir/objc.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bindgen/ir/objc.rs b/bindgen/ir/objc.rs index 65027d38ae..93d8b3bfdf 100644 --- a/bindgen/ir/objc.rs +++ b/bindgen/ir/objc.rs @@ -258,17 +258,17 @@ impl ObjCMethod { if name.is_empty() { None } else if idx == 0 { - // Try to parse the method name as an identifier. Having a keyword is ok + // Try to parse the method name as an identifier. Having a keyword is ok // unless it is `crate`, `self`, `super` or `Self`, so we try to add the `_` // suffix to it and parse it. - Some( - syn::parse_str::(name) - .or_else(|err| { - syn::parse_str::(&format!("{}_", name)) - .map_err(|_| err) - }) - .expect("Invalid identifier"), - ) + if ["crate", "self", "super", "Self"].contains(&name) { + Some(Ident::new( + &format!("{}_", name), + Span::call_site(), + )) + } else { + Some(Ident::new(name, Span::call_site())) + } } else { // Try to parse the current joining name as an identifier. This might fail if the name // is a keyword, so we try to "r#" to it and parse again, this could also fail From 15910e1b9fda7aecc331d13558586d140610426d Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sun, 24 Sep 2023 23:07:41 -0500 Subject: [PATCH 4/5] Update tests --- .../tests/expectations/tests/objc_escape.rs | 30 +++++++++++++++++++ bindgen-tests/tests/headers/objc_escape.h | 6 ++++ 2 files changed, 36 insertions(+) diff --git a/bindgen-tests/tests/expectations/tests/objc_escape.rs b/bindgen-tests/tests/expectations/tests/objc_escape.rs index abf8df602d..1351231d62 100644 --- a/bindgen-tests/tests/expectations/tests/objc_escape.rs +++ b/bindgen-tests/tests/expectations/tests/objc_escape.rs @@ -33,3 +33,33 @@ pub trait IA: Sized + std::ops::Deref { msg_send!(* self, crate_ : self_) } } +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct B(pub id); +impl std::ops::Deref for B { + type Target = objc::runtime::Object; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} +unsafe impl objc::Message for B {} +impl B { + pub fn alloc() -> Self { + Self(unsafe { msg_send!(class!(B), alloc) }) + } +} +impl IB for B {} +pub trait IB: Sized + std::ops::Deref { + unsafe fn type_(&self) -> id + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, type) + } + unsafe fn setType_(&self, type_: id) + where + ::Target: objc::Message + Sized, + { + msg_send!(* self, setType : type_) + } +} diff --git a/bindgen-tests/tests/headers/objc_escape.h b/bindgen-tests/tests/headers/objc_escape.h index 6b52e745be..2d21bd5481 100644 --- a/bindgen-tests/tests/headers/objc_escape.h +++ b/bindgen-tests/tests/headers/objc_escape.h @@ -5,3 +5,9 @@ -(void)f:(int)arg1 as:(int)arg2; -(void)crate:(int)self; @end + +@interface B + +@property(nonatomic, retain) id type; + +@end From 17fb9b018f6b709c4bd6af539dbdae279e93428f Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Wed, 27 Sep 2023 11:11:55 -0500 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2071cc2370..3a43bd966f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -186,6 +186,8 @@ - Allow compiling `bindgen-cli` with a static libclang. - Emit an opaque integer type for pointer types that don't have the same size as the target's pointer size. +- Avoid escaping Objective-C method names unless they are `Self`, `self`, + `crate` or `super`. ## Security # 0.68.1