Closed qarmin closed 1 year ago
Really nice! In order to fix the editor crash, on close, it's necessary to merge this: https://github.com/godotengine/godot/pull/50179 or port Godex to GDExtension. To use GDExtension is needed this feature https://github.com/godotengine/godot/pull/42875 but for GDExtension, reduz is planning to add it at some point before 4.0 is out.
Really nice! In order to fix the editor crash, on close, it's necessary to merge this: https://github.com/godotengine/godot/pull/50179 or port Godex to GDExtension. To use GDExtension is needed this feature https://github.com/godotengine/godot/pull/42875 but for GDExtension, reduz is planning to add it at some point before 4.0 is out.
This crash is related to unit test(editor crashes will be visible later) I think that this is related to this lines, because when iterating over collection, its elements are deleted https://github.com/GodotECS/godex/blob/855d1d7e1c1072faf10f8e751b0ad50fa9fb30ed/pipeline/pipeline_builder.cpp#L932-L936
I added also fuzzer support, but for now crashes due to GDScript bug, because Godot used in Godex is a little too old(1 month behind Godot master branch)
Yup, I need to update it. Also the reason why I'm not merging this is because I'm waiting that the custom iterator is supported in godot. In theory it should arrive soon 🤞
I've updated to latest godot, can you please squash the commits? So we can also trigger again the CI, and see if it pass now.
After rebasing, test project still crash when running project unit tests - https://github.com/GodotECS/godex/issues/272 (https://github.com/qarmin/godex/runs/4475133649?check_suite_focus=true)
Fuzzer crashes when running this code
var temp_variable64 = ClassDB.instantiate("DatabagDynamicFetcher")
temp_variable64.get_meta_list()
temp_variable64.can_translate_messages()
temp_variable64.connect(StringName("."), Callable(BoxMesh.new(),""), Array([]), 79)
temp_variable64.is_class(".")
temp_variable64.has_meta(StringName("3971291559"))
temp_variable64.set_meta(StringName("1684871696"), null)
temp_variable64.is_connected(StringName("1454454129"), Callable(BoxMesh.new(),""))
temp_variable64.set(".", Array([]))
temp_variable64.is_valid()
temp_variable64.disconnect(StringName("3647961650"), Callable(BoxMesh.new(),""))
temp_variable64.has_user_signal(StringName("."))
temp_variable64.to_string()
temp_variable64.get_class()
temp_variable64.add_user_signal(".", Array([]))
temp_variable64.set_indexed(NodePath("2420409340"), Array([]))
temp_variable64.tr_n(StringName("."), StringName("2960212441"), 85, StringName("3784503530"))
temp_variable64.get_signal_connection_list(".")
temp_variable64.get_meta_list()
temp_variable64.can_translate_messages()
temp_variable64.connect(StringName("2370181585"), Callable(BoxMesh.new(),""), Array([]), -62)
temp_variable64.has_method(StringName("."))
temp_variable64.get("1286033485")
ERROR: Index p_index = 3200171710 is out of bounds (count = 23).
at: operator[] (./core/templates/local_vector.h:163)
================================================================
handle_crash: Program crashed with signal 4
Engine version: Godot Engine v4.0.dev.custom_build (534e1d525189bd2aa80e0408eeda3b4898b1f977)
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[1] ./godot/bin/godot.linuxbsd.tools.64s(+0x342b0170) [0x5653634f0170] (??:0)
[2] /lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7ff9314dc210] (??:0)
[3] LocalVector<DatabagInfo, unsigned int, false>::operator[](unsigned int) (??:0)
[4] ECS::unsafe_databag_get_by_name(unsigned int, void const*, StringName const&, Variant&) (??:0)
[5] DatabagDynamicFetcher::_get(StringName const&, Variant&) const (??:0)
[6] DatabagDynamicFetcher::_getv(StringName const&, Variant&) const (??:0)
[7] Object::get(StringName const&, bool*) const (??:0)
[8] Object::_get_bind(String const&) const (??:0)
[9] void call_with_variant_args_retc_helper<__UnexistingClass, Variant, String const&, 0ul>(__UnexistingClass*, Variant (__UnexistingClass::*)(String const&) const, Variant const**, Variant&, Callable::CallError&, IndexSequence<0ul>) (??:0)
[10] void call_with_variant_args_retc_dv<__UnexistingClass, Variant, String const&>(__UnexistingClass*, Variant (__UnexistingClass::*)(String const&) const, Variant const**, int, Variant&, Callable::CallError&, Vector<Variant> const&) (??:0)
[11] MethodBindTRC<Variant, String const&>::call(Object*, Variant const**, int, Callable::CallError&) (??:0)
[12] Object::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[13] DatabagDynamicFetcher::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[14] Object::callv(StringName const&, Array const&) (??:0)
[15] void call_with_variant_args_ret_helper<__UnexistingClass, Variant, StringName const&, Array const&, 0ul, 1ul>(__UnexistingClass*, Variant (__UnexistingClass::*)(StringName const&, Array const&), Variant const**, Variant&, Callable::CallError&, IndexSequence<0ul, 1ul>) (??:0)
[16] void call_with_variant_args_ret_dv<__UnexistingClass, Variant, StringName const&, Array const&>(__UnexistingClass*, Variant (__UnexistingClass::*)(StringName const&, Array const&), Variant const**, int, Variant&, Callable::CallError&, Vector<Variant> const&) (??:0)
[17] MethodBindTR<Variant, StringName const&, Array const&>::call(Object*, Variant const**, int, Callable::CallError&) (??:0)
[18] GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) (??:0)
[19] GDScriptInstance::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[20] Object::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[21] Variant::call(StringName const&, Variant const**, int, Variant&, Callable::CallError&) (??:0)
[22] GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) (??:0)
[23] GDScriptInstance::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[24] Node::_gdvirtual__process_call(double) (??:0)
[25] Node::_notification(int) (??:0)
[26] Node::_notificationv(int, bool) (??:0)
[27] Object::notification(int, bool) (??:0)
[28] SceneTree::_notify_group_pause(StringName const&, int) (??:0)
[29] SceneTree::process(double) (??:0)
[30] Main::iteration() (??:0)
[31] OS_LinuxBSD::run() (??:0)
[32] ./godot/bin/godot.linuxbsd.tools.64s(main+0x414) [0x5653634eda7d] (??:0)
[33] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7ff9314bd0b3] (??:0)
[34] ./godot/bin/godot.linuxbsd.tools.64s(_start+0x2e) [0x5653634ed5ae] (??:0)
-- END OF BACKTRACE --
================================================================
It's kind of expected thought, it's calling the function unsafe_databag_get_by_name
, and it's expected that if the name doesn't exist it crashes. Those APIs are supposed to be called by internal stuff, like the DynamicQuery
, that knows how to use it. I think the test should not use that API, at lest not in that way or directly.
Do you think it's possible to change that?
I added get
to excluded functions(fuzzer_config.txt file)
Other crash
var temp_variable119 = ClassDB.instantiate("DynamicQuery")
temp_variable119.is_connected(StringName("2437906285"), Callable(BoxMesh.new(),""))
temp_variable119.fetch(89)
temp_variable119.not_component(16)
temp_variable119.get_signal_list()
temp_variable119.can_translate_messages()
temp_variable119.maybe_component(88, false)
temp_variable119.notify_property_list_changed()
temp_variable119.reset()
temp_variable119.tr(StringName("."), StringName("."))
temp_variable119.set_message_translation(true)
temp_variable119.end()
temp_variable119.get_component(-30)
temp_variable119.get_meta(StringName("149950933"))
temp_variable119.changed_component(8, true)
temp_variable119.to_string()
temp_variable119.get_script()
temp_variable119.get_current_entity_id()
temp_variable119.has_user_signal(StringName("1481896810"))
temp_variable119.get_signal_connection_list("3824683422")
temp_variable119.set_deferred(StringName("."), Translation.new())
temp_variable119.is_blocking_signals()
temp_variable119.set_space(-28)
temp_variable119.is_class(".")
temp_variable119.has(-1)
temp_variable119.with_component(62, false)
temp_variable119.prepare_world(null)
temp_variable119.has_signal(StringName("878858018"))
temp_variable119.get_meta_list()
temp_variable119.maybe_component(-98, false)
temp_variable119.connect(StringName("."), Callable(BoxMesh.new(),""), Array([]), -60)
temp_variable119.get_class()
temp_variable119.is_queued_for_deletion()
temp_variable119.tr(StringName("2009425479"), StringName("1737654357"))
temp_variable119.set_message_translation(true)
temp_variable119.end()
cause
ERROR: Index p_index = 4294967295 is out of bounds (count = 0).
at: operator[] (./core/templates/local_vector.h:163)
================================================================
handle_crash: Program crashed with signal 4
Engine version: Godot Engine v4.0.dev.custom_build (534e1d525189bd2aa80e0408eeda3b4898b1f977)
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[1] ./godot/bin/godot.linuxbsd.tools.64s(+0x342b0170) [0x55ef44505170] (??:0)
[2] /lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7fd4b2803210] (??:0)
[3] LocalVector<EntityList, unsigned int, false>::operator[](unsigned int) (??:0)
[4] godex::DynamicQuery::conclude_process(World*) (??:0)
[5] godex::DynamicQuery::end_script() (??:0)
[6] void call_with_variant_args_helper<__UnexistingClass>(__UnexistingClass*, void (__UnexistingClass::*)(), Variant const**, Callable::CallError&, IndexSequence<>) (??:0)
[7] void call_with_variant_args_dv<__UnexistingClass>(__UnexistingClass*, void (__UnexistingClass::*)(), Variant const**, int, Callable::CallError&, Vector<Variant> const&) (??:0)
[8] MethodBindT<>::call(Object*, Variant const**, int, Callable::CallError&) (??:0)
[9] Object::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[10] Object::callv(StringName const&, Array const&) (??:0)
[11] void call_with_variant_args_ret_helper<__UnexistingClass, Variant, StringName const&, Array const&, 0ul, 1ul>(__UnexistingClass*, Variant (__UnexistingClass::*)(StringName const&, Array const&), Variant const**, Variant&, Callable::CallError&, IndexSequence<0ul, 1ul>) (??:0)
[12] void call_with_variant_args_ret_dv<__UnexistingClass, Variant, StringName const&, Array const&>(__UnexistingClass*, Variant (__UnexistingClass::*)(StringName const&, Array const&), Variant const**, int, Variant&, Callable::CallError&, Vector<Variant> const&) (??:0)
[13] MethodBindTR<Variant, StringName const&, Array const&>::call(Object*, Variant const**, int, Callable::CallError&) (??:0)
[14] GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) (??:0)
[15] GDScriptInstance::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[16] Object::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[17] Variant::call(StringName const&, Variant const**, int, Variant&, Callable::CallError&) (??:0)
[18] GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) (??:0)
[19] GDScriptInstance::call(StringName const&, Variant const**, int, Callable::CallError&) (??:0)
[20] Node::_gdvirtual__process_call(double) (??:0)
[21] Node::_notification(int) (??:0)
[22] Node::_notificationv(int, bool) (??:0)
[23] Object::notification(int, bool) (??:0)
[24] SceneTree::_notify_group_pause(StringName const&, int) (??:0)
[25] SceneTree::process(double) (??:0)
[26] Main::iteration() (??:0)
[27] OS_LinuxBSD::run() (??:0)
[28] ./godot/bin/godot.linuxbsd.tools.64s(main+0x414) [0x55ef44502a7d] (??:0)
[29] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7fd4b27e40b3] (??:0)
[30] ./godot/bin/godot.linuxbsd.tools.64s(_start+0x2e) [0x55ef445025ae] (??:0)
Same, godex::DynamicQuery
is created assuming that it's impossible to use it directly. It's almost always wrapped by something else, so you can't mess with it. If i make it safe, will pass this CI but will be slower for no reason.
So which classes from this can user use?
Component
ComponentDynamicExposer
Components3DGizmoPlugin
DatabagDynamicFetcher
DynamicQuery
ECS
Entity2D
Entity3D
EventsEmitterDynamicFetcher
EventsReceiverDynamicFetcher
GodexWorldFetcher
PipelineECS
ScriptEcs
SharedComponentResource
StorageDynamicFetcher
System
SystemBundle
TextServerFallback
WorldECS
WorldECS
, World
, Query
. (There is no other way to obtain that object in GDS, if not using those classes) https://github.com/GodotECS/godex/blob/main/utils/fetchers.hWorldECS
, World
, Query
. (There is no other way to obtain that object in GDS, if not using those classes) https://github.com/GodotECS/godex/blob/main/utils/fetchers.hunsafe_
(those are internal for internal use only). https://github.com/GodotECS/godex/blob/main/ecs.hWorldECS
, World
, Query
. (There is no other way to obtain that object in GDS, if not using those classes) https://github.com/GodotECS/godex/blob/main/utils/fetchers.hWorldECS
, World
, Query
. (There is no other way to obtain that object in GDS, if not using those classes) https://github.com/GodotECS/godex/blob/main/utils/fetchers.hWorldECS
, World
, Query
. (There is no other way to obtain that object in GDS, if not using those classes) https://github.com/GodotECS/godex/blob/main/utils/fetchers.hWorldECS
, World
, Query
. (There is no other way to obtain that object in GDS, if not using those classes) https://github.com/GodotECS/godex/blob/main/utils/fetchers.h_prepare
function. However we can assume all functions are safe, with exception of the static methods. https://github.com/GodotECS/godex/blob/main/modules/godot/nodes/ecs_utilities.h_prepare
function. However we can assume all functions are safe, with exception of the static methods. https://github.com/GodotECS/godex/blob/main/modules/godot/nodes/ecs_utilities.h
In this CI, Godex is compiled with address sanitizer.
Also editor is opened and closed.
As test project I choose - https://github.com/qarmin/RegressionTestProject/ - but it can be removed or changed(new project should be reproducible)
Not sure if I properly compiled Godex but I see this crash in unit tests