Skip to content
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

Fix no cast in Ref<T>::ref() #469

Closed
wants to merge 1 commit into from
Closed

Fix no cast in Ref<T>::ref() #469

wants to merge 1 commit into from

Conversation

DmitriySalnikov
Copy link
Contributor

@DmitriySalnikov DmitriySalnikov commented Nov 16, 2020

Godot versions:
Windows 3.2.4 godotengine/godot#43554
Linux 3.2.3.stable
GDNative: #451

On Windows with the current Ref implementation on master brach, this code will crash after the first get_position because the reference is actualy nullptr for InputEventScreenTouch type and it has same address as iemb reference.

Ref<InputEventMouseButton> iemb(InputEventMouseButton::_new());
iemb->set_position(Vector2(12312312, 412421));

Ref<InputEventScreenTouch> iest = iemb;
if (iest.is_valid()) {
	Godot::print("cast 1");
	Godot::print(iest->get_position().operator godot::String());
}

Ref<InputEventScreenDrag> iesd(iemb);
if (iesd.is_valid()) {
	Godot::print("cast 2");
	Godot::print(iesd->get_position().operator godot::String());
}

Ref<InputEventScreenDrag> ie_null;
if (ie_null.is_valid()) {
	Godot::print("null");
	Godot::print(ie_null->get_position().operator godot::String());
}

Ref<InputEventMouseButton> iemb2(iemb);
if (iemb2.is_valid()) {
	Godot::print("same type");
	Godot::print(iemb2->get_position().operator godot::String());
}

image

On Linux no crash occurs but types not casted correctly too. Linux just use wrong memory segment and display zeroes or random values.
image

After this fix, the behavior of Windows and Linux is the same and correct as in normal modules
image

Also I tested this with my custom classes

Ref<GRPacketClientStreamAspect> a = GRPacketClientStreamAspect::_new();
a->set_aspect(0.99f);
if (a.is_valid()) {
	Godot::print("a");
	Godot::print(String::num_real(a->get_aspect()));
}

Ref<GRPacketServerSettings> b = a;
if (b.is_valid()) {
	Godot::print("b");
	Godot::print(b->get_settings()[0]);
}

Ref<GRPacketClientStreamOrientation> c = a;
if (c.is_valid()) {
	Godot::print("c");
	Godot::print(String::num_int64(c->is_vertical()));
}
Reference
└─GRPacket
  ├─GRPacketClientStreamAspect
  ├─GRPacketServerSettings
  ├─GRPacketClientStreamOrientation
  └─...

Without a fix Windows and Linux builds crashed on call to invalid Dictionary

a
0.99
b
handle_crash: Program crashed with signal 11
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[1] /lib/x86_64-linux-gnu/libc.so.6(+0x37840) [0x7f89afe3b840] (??:0)
[2] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0xde95cf] (??:?)
[3] godot::Dictionary::Dictionary(godot::Dictionary const&) (??:0)
[4] GRPacketServerSettings::get_settings() (??:0)
[5] GodotRemote::_init() (??:0)
[6] void* godot::_godot_class_instance_func<GodotRemote>(void*, void*) (??:0)
[7] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0x261c419] (<artificial>:?)
[8] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0xc63098] (??:?)
[9] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0xc6346b] (??:?)
[10] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0x12f99bf] (<artificial>:?)
[11] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0x12fb12e] (??:?)
[12] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0x2a77afa] (<artificial>:?)
[13] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0x85ce0d] (??:?)
[14] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xeb) [0x7f89afe2809b] (??:0)
[15] /home/dima/Desktop/Godot_v3.2.3-stable_x11.64() [0x86b68e] (??:?)
-- END OF BACKTRACE --

With fix:
image

Now the original Godot code and the code here are not the same, but now it works for me.

@Calinou Calinou added the bug This has been identified as a bug label Nov 16, 2020
@DmitriySalnikov
Copy link
Contributor Author

DmitriySalnikov commented Nov 16, 2020

I'm not sure but maybe more leak tests are needed

@@ -21,7 +21,7 @@ class Ref {

unref();

reference = p_from.reference;
reference = Object::cast_to<T>(p_from.reference);
Copy link
Collaborator

@Zylann Zylann Dec 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cast makes sense, but looks like the location is not right. ref here expects a reference where T is the same between the source and destination references. I'm not even sure why it gets called (or even compiling?) while InputEventScreenTouch and InputEventMouseButton are incompatible types? Or perhaps the syntax without T means "any T"? I see it's used with the basic Reference somewhere so it might be a problem.
I would have expected this cast to occur in a function that expects a different T. If T is the same, no cast should occur, otherwise it would slow down every place the wrapper is assigned.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok the real place to put the cast should actually be the places with // TODO We need a safe cast.
The reason ref ends up assigning the pointer is because of a cast that happened already, but it was done without any check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.
Can I close this pull request and let you fix this issue?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm working on a fix, though having a bit of trouble enforcing T being a Reference at compile-time... might be able to fix the cast but to have the extra nicety it might need more work

@Zylann
Copy link
Collaborator

Zylann commented Dec 8, 2020

New PR: #480

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
archived bug This has been identified as a bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants