Skip to content

Commit 002d5d6

Browse files
committed
Catch null object pointers in Variant::is_nil
With varcall, Godot sometimes return null objects as Variants with `VariantType::Object` but a null pointer, instead of the usually expected/assumed `VariantType::Nil`. This caused `Option::from_variant` to panic in case of null objects returned by Godot in this way. Fix #1001
1 parent 8ac4fae commit 002d5d6

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

gdnative-core/src/core_types/variant.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,14 @@ impl Variant {
451451
/// Returns true if this is an empty variant.
452452
#[inline]
453453
pub fn is_nil(&self) -> bool {
454-
self.get_type() == VariantType::Nil
454+
match self.get_type() {
455+
VariantType::Nil => true,
456+
VariantType::Object => {
457+
let ptr = unsafe { (get_api().godot_variant_as_object)(&self.0) };
458+
ptr.is_null()
459+
}
460+
_ => false,
461+
}
455462
}
456463

457464
#[inline]

test/src/lib.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ pub extern "C" fn run_tests(
6969
status &= gdnative::core_types::test_vector3_array_debug();
7070
status &= gdnative::core_types::test_transform2d_behavior();
7171

72-
status &= test_underscore_method_binding();
73-
status &= test_rust_class_construction();
7472
status &= test_from_instance_id();
73+
status &= test_nil_object_return_value();
74+
status &= test_rust_class_construction();
75+
status &= test_underscore_method_binding();
7576

7677
status &= test_as_arg::run_tests();
7778
status &= test_async::run_tests();
@@ -91,11 +92,20 @@ pub extern "C" fn run_tests(
9192
Variant::new(status).leak()
9293
}
9394

94-
godot_itest! { test_underscore_method_binding {
95-
let script = gdnative::api::NativeScript::new();
96-
let result = script._new(&[]);
97-
assert_eq!(Variant::nil(), result);
98-
}}
95+
godot_itest! {
96+
test_underscore_method_binding {
97+
let script = gdnative::api::NativeScript::new();
98+
let result = script._new(&[]);
99+
assert_eq!(Variant::nil(), result);
100+
}
101+
102+
test_nil_object_return_value {
103+
let node = Node::new();
104+
// Should not panic due to conversion failure
105+
let option = node.get_node("does not exist");
106+
assert!(option.is_none());
107+
}
108+
}
99109

100110
#[derive(NativeClass)]
101111
#[inherit(Reference)]

0 commit comments

Comments
 (0)