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

Crash when duplicating an editor internal node #90991

Closed
LeaoLuciano opened this issue Apr 21, 2024 · 4 comments · Fixed by #90992
Closed

Crash when duplicating an editor internal node #90991

LeaoLuciano opened this issue Apr 21, 2024 · 4 comments · Fixed by #90992

Comments

@LeaoLuciano
Copy link
Contributor

Tested versions

  • v4.3.dev.custom_build.4a0160241

System information

Linux

Issue description

Trying to duplicate a node that class isn't exposed by ClassDB results in a segfault.

This happens because the node created by Node::duplicate() is instantiated using ClassDB:

godot/scene/main/node.cpp

Lines 2656 to 2661 in 4a01602

Object *obj = ClassDB::instantiate(get_class());
ERR_FAIL_NULL_V(obj, nullptr);
node = Object::cast_to<Node>(obj);
if (!node) {
memdelete(obj);
}

Backtrace:

================================================================
handle_crash: Program crashed with signal 11
Engine version: Godot Engine v4.3.dev.custom_build (4a0160241fd0c1e874e297f6b08676cf0761e5e8)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] godotasan(+0x843a901) [0x55c2f8771901] (platform/linuxbsd/crash_handler_linuxbsd.cpp:61 (discriminator 1))
[2] /usr/lib/libc.so.6(+0x40770) [0x7f7fa9fb6770] (??:0)
[3] Object::get_property_list(List<PropertyInfo, DefaultAllocator>*, bool) const (core/object/object.cpp:484)
[4] Node::_duplicate_properties_node(Node const*, Node const*, Node*) const (scene/main/node.cpp:2906)
[5] Node::duplicate(int) const (scene/main/node.cpp:2825)
[6] void call_with_variant_args_retc_helper<__UnexistingClass, Node*, int, 0ul>(__UnexistingClass*, Node* (__UnexistingClass::*)(int) const, Variant const**, Variant&, Callable::CallError&, IndexSequence<0ul>) (./core/variant/binder_common.h:807 (discriminator 1))
[7] void call_with_variant_args_retc_dv<__UnexistingClass, Node*, int>(__UnexistingClass*, Node* (__UnexistingClass::*)(int) const, Variant const**, int, Variant&, Callable::CallError&, Vector<Variant> const&) (./core/variant/binder_common.h:539)
[8] MethodBindTRC<Node*, int>::call(Object*, Variant const**, int, Callable::CallError&) const (./core/object/method_bind.h:619 (discriminator 1))
[9] GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) (modules/gdscript/gdscript_vm.cpp:1828 (discriminator 2))
[10] GDScriptLambdaSelfCallable::call(Variant const**, int, Variant&, Callable::CallError&) const (modules/gdscript/gdscript_lambda_callable.cpp:275 (discriminator 3))
[11] Callable::callp(Variant const**, int, Variant&, Callable::CallError&) const (core/variant/callable.cpp:57)
[12] CallQueue::_call_function(Callable const&, Variant const*, int, bool) (core/object/message_queue.cpp:222)
[13] CallQueue::flush() (core/object/message_queue.cpp:328)
[14] SceneTree::physics_process(double) (scene/main/scene_tree.cpp:495)
[15] Main::iteration() (main/main.cpp:3988 (discriminator 3))
[16] OS_LinuxBSD::run() (platform/linuxbsd/os_linuxbsd.cpp:962 (discriminator 1))
[17] godotasan(main+0x34a) [0x55c2f8771503] (platform/linuxbsd/godot_linuxbsd.cpp:85)
[18] /usr/lib/libc.so.6(+0x29cd0) [0x7f7fa9f9fcd0] (??:0)
[19] /usr/lib/libc.so.6(__libc_start_main+0x8a) [0x7f7fa9f9fd8a] (??:0)
[20] godotasan(_start+0x25) [0x55c2f87710e5] (??:?)
-- END OF BACKTRACE --
================================================================

Steps to reproduce

Search for a node named "SceneTreeEditor" in the editor scene tree using a @tool script and duplicate it:

var q = [get_tree().root]
var scene_tree_editor: Node

while not q.is_empty():
	var node: Node = q.pop_front()

	if node.name == "SceneTreeEditor":
		print(node)
		scene_tree_editor = node.duplicate()
		break
	
	q.append_array(node.get_children())

Minimal reproduction project (MRP)

MRP: scene_tree_editor_crash.zip (open node.tscn in the editor to reproduce the crash)

@radiantgurl
Copy link
Contributor

According to the stack trace, it doesnt even happen inside _duplicate.

@LeaoLuciano
Copy link
Contributor Author

LeaoLuciano commented Apr 21, 2024

According to the stack trace, it doesnt even happen inside _duplicate.

The segfault happens here:

godot/scene/main/node.cpp

Lines 2903 to 2905 in 4a01602

void Node::_duplicate_properties_node(const Node *p_root, const Node *p_original, Node *p_copy) const {
List<PropertyInfo> props;
p_copy->get_property_list(&props);

because p_copy is null (discovered using gdb).
p_copy's value came from dupe:

godot/scene/main/node.cpp

Lines 2815 to 2826 in 4a01602

Node *Node::duplicate(int p_flags) const {
ERR_THREAD_GUARD_V(nullptr);
Node *dupe = _duplicate(p_flags);
if (dupe && (p_flags & DUPLICATE_SIGNALS)) {
_duplicate_signals(this, dupe);
}
_duplicate_properties_node(this, this, dupe);
return dupe;
}

And dupe is the return value of _duplicate which is node:

godot/scene/main/node.cpp

Lines 2656 to 2661 in 4a01602

Object *obj = ClassDB::instantiate(get_class());
ERR_FAIL_NULL_V(obj, nullptr);
node = Object::cast_to<Node>(obj);
if (!node) {
memdelete(obj);
}

@radiantgurl
Copy link
Contributor

I'll definitely take a look at this.

@LeaoLuciano
Copy link
Contributor Author

Thanks!

@AThousandShips AThousandShips added this to the 4.3 milestone Apr 22, 2024
@KoBeWi KoBeWi removed this from the 4.3 milestone Aug 3, 2024
@akien-mga akien-mga added this to the 4.4 milestone Aug 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants