-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
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
[Core] Fix Variant::construct
of Object
#90134
Conversation
@@ -153,11 +153,12 @@ class VariantConstructor { | |||
class VariantConstructorObject { | |||
public: | |||
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { | |||
VariantInternal::clear(&r_ret); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving this below matches the rest of the cases, where errors mean we don't touch it, can move it back above if desired, but take VariantConstructorNilObject
for example
The reason it breaks GDScript in this case is that this code passes fine, as godot/modules/gdscript/gdscript.cpp Line 1609 in 29b3d9e
|
This comment was marked as outdated.
This comment was marked as outdated.
There's still a strange leak when using Edit: Got a fix for this, part too, but will look at some other potential areas as well Edit 2: Realized why, will improve This issue was caused by that |
aa0bd93
to
6b70b1b
Compare
There, new fix, this is perhaps not exactly the cleanest, but I prefer to use the methods available there instead of assigning directly to the type, an alterative solution would be to instead (diff on top of this PR): diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index 40e0d37360..b5cd7ff1e7 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -154,12 +154,10 @@ class VariantConstructorObject {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
if (p_args[0]->get_type() == Variant::NIL) {
- VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign_null(&r_ret);
r_error.error = Callable::CallError::CALL_OK;
} else if (p_args[0]->get_type() == Variant::OBJECT) {
- VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign(&r_ret, p_args[0]);
r_error.error = Callable::CallError::CALL_OK;
@@ -171,7 +169,6 @@ public:
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
- VariantInternal::clear(r_ret);
VariantTypeChanger<Object *>::change(r_ret);
VariantInternal::object_assign(r_ret, p_args[0]);
}
@@ -201,13 +198,11 @@ public:
r_error.expected = Variant::NIL;
}
- VariantInternal::clear(&r_ret);
VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign_null(&r_ret);
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
- VariantInternal::clear(r_ret);
VariantTypeChanger<Object *>::change(r_ret);
VariantInternal::object_assign_null(r_ret);
}
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index dbd4a6a7ad..d867d08b2c 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -1493,13 +1493,13 @@ struct VariantDefaultInitializer<PackedColorArray> {
template <typename T>
struct VariantTypeChanger {
static _FORCE_INLINE_ void change(Variant *v) {
- if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer
+ if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE == Variant::OBJECT || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer
VariantInternal::clear(v);
VariantInitializer<T>::init(v);
}
}
static _FORCE_INLINE_ void change_and_reset(Variant *v) {
- if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer
+ if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE == Variant::OBJECT || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer
VariantInternal::clear(v);
VariantInitializer<T>::init(v);
} And just use the Will see if I can add a test for leaks as well Edit: Added a test for the leak, will push when CI is done |
6b70b1b
to
710b70c
Compare
710b70c
to
fd32fe0
Compare
fd32fe0
to
74f8ba6
Compare
74f8ba6
to
f6773c9
Compare
Variant type was not updated correctly causing leaks in ref-counted
f6773c9
to
8f3e2c9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Should be safe to merge too.
Thanks! |
Thank you! |
Variant type was not updated correctly causing leaks in ref-counted
This caused errors as objects constructed this way would be typed
NIL
and therefore not be freed, even though they went through reference counting, might have caused further issues elsewhere, like extensions, but haven't tested, this should be a safe fix as it just clears and initializes the typeweakref()
#90086