Skip to content

Commit 27af81b

Browse files
committed
All GDNative methods accepting Rid parameters are now unsafe
1 parent c1c1354 commit 27af81b

File tree

2 files changed

+29
-9
lines changed

2 files changed

+29
-9
lines changed

bindings_generator/src/api.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ impl GodotArgument {
324324
}
325325
}
326326

327-
#[derive(Clone)]
327+
#[derive(Clone, Eq, PartialEq)]
328328
pub enum Ty {
329329
Void,
330330
String,

bindings_generator/src/methods.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -344,20 +344,19 @@ pub(crate) fn generate_methods(
344344
let icall_name = method_sig.function_name();
345345
let icall = format_ident!("{}", icall_name);
346346

347-
icalls.insert(icall_name.clone(), method_sig);
348-
349-
let rusty_name = rust_safe_name(rusty_method_name);
350-
351347
let maybe_unsafe: TokenStream;
352348
let maybe_unsafe_reason: &str;
353-
if UNSAFE_OBJECT_METHODS.contains(&(&class.name, method_name)) {
349+
if let Some(unsafe_reason) = unsafe_reason(class, method_name, &method_sig) {
354350
maybe_unsafe = quote! { unsafe };
355-
maybe_unsafe_reason = "\n# Safety\nThis function bypasses Rust's static type checks \
356-
(aliasing, thread boundaries, calls to free(), ...).";
351+
maybe_unsafe_reason = unsafe_reason;
357352
} else {
358353
maybe_unsafe = TokenStream::default();
359354
maybe_unsafe_reason = "";
360-
};
355+
}
356+
357+
icalls.insert(icall_name.clone(), method_sig);
358+
359+
let rusty_name = rust_safe_name(rusty_method_name);
361360

362361
let method_bind_fetch = {
363362
let method_table = format_ident!("{}MethodTable", class.name);
@@ -394,6 +393,27 @@ pub(crate) fn generate_methods(
394393
result
395394
}
396395

396+
/// Returns a message as to why this method would be unsafe; or None if the method is safe
397+
fn unsafe_reason(
398+
class: &GodotClass,
399+
method_name: &str,
400+
method_sig: &MethodSig,
401+
) -> Option<&'static str> {
402+
if UNSAFE_OBJECT_METHODS.contains(&(&class.name, method_name)) {
403+
Some(
404+
"\n# Safety\
405+
\nThis function bypasses Rust's static type checks (aliasing, thread boundaries, calls to free(), ...).",
406+
)
407+
} else if method_sig.arguments.contains(&Ty::Rid) {
408+
Some(
409+
"\n# Safety\
410+
\nThis function has parameters of type `Rid` (resource ID). \
411+
RIDs are untyped and interpreted as raw pointers by the engine, so passing an incorrect RID can cause UB.")
412+
} else {
413+
None
414+
}
415+
}
416+
397417
fn ret_recover(ty: &Ty, icall_ty: IcallType) -> TokenStream {
398418
match icall_ty {
399419
IcallType::Ptr => ty.to_return_post(),

0 commit comments

Comments
 (0)