-
Notifications
You must be signed in to change notification settings - Fork 210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust's newly added assert_unsafe_precondition
makes GDNative .dlls that are compiled in debug mode crash on startup
#1077
Comments
Starting from Rust 1.78, debug builds now check for gdnative/gdnative-core/src/export/method.rs Lines 320 to 322 in 639aae7
The rationale for considering I'm currently using this a quick workaround: let args = if num_args > 0 { std::slice::from_raw_parts(args, num_args as usize) } else { &[] }; ...but it may be sub-optimal, as it adds a branching condition in a pretty hot path. So maybe there's a better way to introduce a validation for zero-length slices and prevent passing |
Can confirm that I'm experiencing this under Ubuntu 20.04 (Linux 64-bit) with Rust 0.78.0 and Godot 3.5.3. Can also confirm that the workaround fixed the crash here - thanks so much for sharing it! :) |
Iterating on the workaround, I've adjusted my copy of pub unsafe fn from_sys(num_args: libc::c_int, args: *mut *mut sys::godot_variant) -> Self {
let args = Self::safe_args(num_args, args);
let args = std::mem::transmute::<&[*mut sys::godot_variant], &[&Variant]>(args);
Self {
idx: 0,
args,
offset_index: 0,
}
}
/// Convert args to a slice in debug builds - avoids crash when using Rust 1.78 and beyond
#[doc(hidden)]
#[inline]
#[cfg(debug_assertions)]
unsafe fn safe_args(
num_args: libc::c_int,
args: *mut *mut sys::godot_variant,
) -> &'a [*mut sys::godot_variant] {
if num_args > 0 {
std::slice::from_raw_parts(args, num_args as usize)
} else {
&[]
}
}
/// Convert args to a slice in release builds - using more effecient code than the version above
#[doc(hidden)]
#[inline]
#[cfg(not(debug_assertions))]
unsafe fn safe_args(
num_args: libc::c_int,
args: *mut *mut sys::godot_variant,
) -> &'a [*mut sys::godot_variant] {
std::slice::from_raw_parts(args, num_args as usize)
} |
the only way to avoid such a branch is by simply keeping it as a pointer, instead of turning it into a slice, but that would take some work. |
Minimal reproducible project:
GDNative - Bug Reproduction.zip
Compiled using Rust version
1.79.0-nightly (8b2459c1f 2024-04-09)
.Godot version: 3.5.3
Platform: Windows 10 64 bit
How to Reproduce
cargo build
in the directory "rust")Steps 1 and 2 can also be done by running "build_and_move_debug.bat"
Since
assert_unsafe_precondition
is stripped in release mode, this bug only happens in debug mode.This can be proven by mimicking the reproduction steps but compiling in release mode:
cargo build --release
in the directory "rust")Steps 1 and 2 can also be done by running "build_and_move_release.bat"
Additional info
When using the panic handler recipe in the book, it manages to catch a stack trace of the first error:
This stack trace was gathered on another project though, here's the script:
Current workaround is to simply not use debug mode, but that disables some useful assertions made by GDNative that can catch many UB cases.
The text was updated successfully, but these errors were encountered: