Clicking scene instantiated via @tool script crashes editor
Tested versions
v4.3.stable.official [77dcf97d8]
System information
Godot v4.3.stable - Windows 10.0.22631 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 2070 SUPER (NVIDIA; 32.0.15.6081) - AMD Ryzen 7 3800X 8-Core Processor (16 Threads)
Issue description
Clicking on the object in editor instantiated with following script crashes the editor.
Console output: Couldn't see if there was anything else printed above the same 27 lines:
[1] error(-1): no debug info in PE/COFF executable
.....
[27] error(-1): no debug info in PE/COFF executable
-- END OF BACKTRACE --
Steps to reproduce
Script:
@tool
extends Node
const BLOCK = preload("res://block.tscn")
func _ready() -> void:
var block = BLOCK.instantiate()
add_child(block)
Block scene:
Minimal reproduction project (MRP)
ToolCrashTest 26.08.2024 14.47.38.zip
Open test scene and click on the cube.
This appears to be fixed in v4.3.1.rc.custom_build [ff9bc0422] & v4.4.dev.custom_build [804454240].
Can you confirm?
This appears to be fixed in v4.3.1.rc.custom_build [ff9bc04] & v4.4.dev.custom_build [804454240].
4.3.1.rc ff9bc04 is basically the same as 4.3.stable, nothing has been cherry-picked yet (the only difference is the version number). So if it's reproducible in official builds of 4.3.stable, and not in custom builds, it means the compiler is the main difference (official builds are made with mingw-gcc).
Bisecting points to #92188 as the culprit, @SaracenOne :
================================================================
CrashHandlerException: Program crashed
Engine version: Godot Engine v4.4.dev.custom_build (e63c40e59c6650bdba02c2ceff3390ee9273ac46)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[0] Node3DEditorViewport::_is_node_locked (C:\Users\Matheus\Downloads\Godot Source\editor\plugins\node_3d_editor_plugin.cpp:1561)
[1] Node3DEditorViewport::_is_node_locked (C:\Users\Matheus\Downloads\Godot Source\editor\plugins\node_3d_editor_plugin.cpp:1561)
[2] Node3DEditorViewport::_select_clicked (C:\Users\Matheus\Downloads\Godot Source\editor\plugins\node_3d_editor_plugin.cpp:773)
[3] Node3DEditorViewport::_sinput (C:\Users\Matheus\Downloads\Godot Source\editor\plugins\node_3d_editor_plugin.cpp:1952)
[4] call_with_variant_args_helper<Node3DEditorViewport,Ref<InputEvent> const &,0> (C:\Users\Matheus\Downloads\Godot Source\core\variant\binder_common.h:304)
[5] call_with_variant_args<Node3DEditorViewport,Ref<InputEvent> const &> (C:\Users\Matheus\Downloads\Godot Source\core\variant\binder_common.h:419)
[6] CallableCustomMethodPointer<Node3DEditorViewport,Ref<InputEvent> const &>::call (C:\Users\Matheus\Downloads\Godot Source\core\object\callable_method_pointer.h:104)
[7] Callable::callp (C:\Users\Matheus\Downloads\Godot Source\core\variant\callable.cpp:58)
[8] Object::emit_signalp (C:\Users\Matheus\Downloads\Godot Source\core\object\object.cpp:1191)
[9] Node::emit_signalp (C:\Users\Matheus\Downloads\Godot Source\scene\main\node.cpp:3929)
[10] Object::emit_signal<Ref<InputEvent> > (C:\Users\Matheus\Downloads\Godot Source\core\object\object.h:940)
[11] Control::_call_gui_input (C:\Users\Matheus\Downloads\Godot Source\scene\gui\control.cpp:1820)
[12] Viewport::_gui_call_input (C:\Users\Matheus\Downloads\Godot Source\scene\main\viewport.cpp:1571)
[13] Viewport::_gui_input_event (C:\Users\Matheus\Downloads\Godot Source\scene\main\viewport.cpp:1837)
[14] Viewport::push_input (C:\Users\Matheus\Downloads\Godot Source\scene\main\viewport.cpp:3260)
[15] Window::_window_input (C:\Users\Matheus\Downloads\Godot Source\scene\main\window.cpp:1682)
[16] call_with_variant_args_helper<Window,Ref<InputEvent> const &,0> (C:\Users\Matheus\Downloads\Godot Source\core\variant\binder_common.h:304)
[17] call_with_variant_args<Window,Ref<InputEvent> const &> (C:\Users\Matheus\Downloads\Godot Source\core\variant\binder_common.h:419)
[18] CallableCustomMethodPointer<Window,Ref<InputEvent> const &>::call (C:\Users\Matheus\Downloads\Godot Source\core\object\callable_method_pointer.h:104)
[19] Callable::callp (C:\Users\Matheus\Downloads\Godot Source\core\variant\callable.cpp:58)
[20] Callable::call<Ref<InputEvent> > (C:\Users\Matheus\Downloads\Godot Source\core\variant\variant.h:876)
[21] DisplayServerWindows::_dispatch_input_event (C:\Users\Matheus\Downloads\Godot Source\platform\windows\display_server_windows.cpp:3703)
[22] DisplayServerWindows::_dispatch_input_events (C:\Users\Matheus\Downloads\Godot Source\platform\windows\display_server_windows.cpp:3674)
[23] Input::_parse_input_event_impl (C:\Users\Matheus\Downloads\Godot Source\core\input\input.cpp:803)
[24] Input::flush_buffered_events (C:\Users\Matheus\Downloads\Godot Source\core\input\input.cpp:1084)
[25] DisplayServerWindows::process_events (C:\Users\Matheus\Downloads\Godot Source\platform\windows\display_server_windows.cpp:3157)
[26] OS_Windows::run (C:\Users\Matheus\Downloads\Godot Source\platform\windows\os_windows.cpp:1666)
[27] widechar_main (C:\Users\Matheus\Downloads\Godot Source\platform\windows\godot_windows.cpp:181)
[28] _main (C:\Users\Matheus\Downloads\Godot Source\platform\windows\godot_windows.cpp:206)
[29] main (C:\Users\Matheus\Downloads\Godot Source\platform\windows\godot_windows.cpp:220)
[30] WinMain (C:\Users\Matheus\Downloads\Godot Source\platform\windows\godot_windows.cpp:234)
[31] __scrt_common_main_seh (D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
[32] <couldn't map PC to fn name>
-- END OF BACKTRACE --
================================================================
It looks like the problem is a null pointer being passed to Node3DEditorViewport::_is_node_locked as a result of the changed code in Node3DEditorViewport::_select_clicked in the case that there is no editable parent of the clicked Node3D:
https://github.com/godotengine/godot/blob/142d33211cb4276dee6f797117981af983471b9e/editor/plugins/node_3d_editor_plugin.cpp#L741-L773
From debugging the provided MRP, it appears that the new code on lines 753-760 that walks up the scene tree to find the nearest selectable parent sets selected to null in the case that there is no selectable parent (such as in the case with the tool script). This null pointer is then passed into _is_node_locked on line 773, which does not check if the passed pointer is null and attempts to call get_meta on the null pointer, causing the bad memory access and crash.
To avoid a crash, there should probably be a null pointer check on the selected pointer, either inside of _is_node_locked (not sure what the correct default would be), or before attempting to check if the node is locked in _select_clicked, replacing line 773 with:
if (p_allow_locked || (selected != nullptr && !_is_node_locked(selected))) {
similar to the check on line 755. Making this change solves the problem on macos.arm64, with the click having no effect rather than crashing the editor, which I believe is the intended behaviour. If this is the correct approach I can put that small change in a PR.