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

Executing MultiMesh._get_transform_2d_array function crashes Godot with GLES3 #92038

Open
qarmin opened this issue May 17, 2024 · 3 comments
Open

Comments

@qarmin
Copy link
Contributor

qarmin commented May 17, 2024

Tested versions

4.3 c27f24d

System information

Ubuntu 22.04 CI

Issue description

When executing (this code was automatically minimized, so it is possible, that an even more "minimal" project can be created)

extends Node
func _process(delta):
	var temp_variable878 = MultiMesh.new()
	temp_variable878.property_get_revert(StringName("."))
	temp_variable878.set_instance_count(18)
	temp_variable878._get_transform_2d_array()
	temp_variable878.get_method_argument_count(StringName("."))
	temp_variable878.set_buffer(PackedFloat32Array([81.8810119628906, -37.9453048706055, 7.53989219665527, 6.33658170700073, 48.5376014709473, -56.5251426696777, 36.5014190673828, -39.4767036437988, -62.3482704162598, 99.3360900878906, 12.1148347854614, -52.8599128723145, 1.81378126144409, -41.4583511352539, 0, 99.078498840332, 85.0770950317383, -69.0927352905273, -88.7104034423828, -4.80872392654419, -19.7792835235596, 57.4738006591797, 57.2557907104492, -88.3957595825195, 98.5607528686523]))
	temp_variable878._get_transform_2d_array()

Godot crashes:

Godot Engine v4.3.beta.custom_build - https://godotengine.org
MESA: error: ZINK: failed to choose pdev
glx: failed to create drisw screen
failed to load driver: zink
######################## Ending test ########################
ERROR: Condition "p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)" is true.
   at: multimesh_set_buffer (drivers/gles3/storage/mesh_storage.cpp:1945)
=================================================================
==22835==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60e001451c40 at pc 0x562aa24888f2 bp 0x7ffde9d890b0 sp 0x7ffde9d890a0
READ of size 4 at 0x60e001451c40 thread T0
    #0 0x562aa24888f1 in GLES3::MeshStorage::multimesh_instance_get_transform_2d(RID, int) const drivers/gles3/storage/mesh_storage.cpp:1826
    #1 0x562ab2a4882d in RenderingServerDefault::multimesh_instance_get_transform_2d(RID, int) const servers/rendering/rendering_server_default.h:340
    #2 0x562aaed9be56 in MultiMesh::get_instance_transform_2d(int) const scene/resources/multimesh.cpp:253
    #3 0x562aaed9687c in MultiMesh::_get_transform_2d_array() const scene/resources/multimesh.cpp:127
    #4 0x562a9b3d01cb in void call_with_variant_args_retc_helper<__UnexistingClass, Vector<Vector2>>(__UnexistingClass*, Vector<Vector2> (__UnexistingClass::*)() const, Variant const**, Variant&, Callable::CallError&, IndexSequence<>) core/variant/binder_common.h:807
    #5 0x562a9b3b8d9f in void call_with_variant_args_retc_dv<__UnexistingClass, Vector<Vector2>>(__UnexistingClass*, Vector<Vector2> (__UnexistingClass::*)() const, Variant const**, int, Variant&, Callable::CallError&, Vector<Variant> const&) core/variant/binder_common.h:568
    #6 0x562a9b38c428 in MethodBindTRC<Vector<Vector2>>::call(Object*, Variant const**, int, Callable::CallError&) const core/object/method_bind.h:620
    #7 0x562ab78638e9 in Object::callp(StringName const&, Variant const**, int, Callable::CallError&) core/object/object.cpp:841
    #8 0x562ab6b5fffc in Variant::callp(StringName const&, Variant const**, int, Variant&, Callable::CallError&) core/variant/variant_call.cpp:1211
    #9 0x562a9c380583 in GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) modules/gdscript/gdscript_vm.cpp:1767
    #10 0x562a9bc01a8d in GDScriptInstance::callp(StringName const&, Variant const**, int, Callable::CallError&) modules/gdscript/gdscript.cpp:2006
    #11 0x562aa9e83a4a in bool Node::_gdvirtual__process_call<false>(double) scene/main/node.h:351
    #12 0x562aa9db1199 in Node::_notification(int) scene/main/node.cpp:55
    #13 0x562a9b25fedf in Node::_notificationv(int, bool) scene/main/node.h:50
    #14 0x562ab7865472 in Object::notification(int, bool) core/object/object.cpp:903
    #15 0x562aa9fbe4a4 in SceneTree::_process_group(SceneTree::ProcessGroup*, bool) scene/main/scene_tree.cpp:962
    #16 0x562aa9fc1740 in SceneTree::_process(bool) scene/main/scene_tree.cpp:1039
    #17 0x562aa9fb06cb in SceneTree::process(double) scene/main/scene_tree.cpp:526
    #18 0x562a9a8a3dca in Main::iteration() main/main.cpp:4052
    #19 0x562a9a599bb1 in OS_LinuxBSD::run() platform/linuxbsd/os_linuxbsd.cpp:962
    #20 0x562a9a5789ff in main platform/linuxbsd/godot_linuxbsd.cpp:85
    #21 0x7ff16c229d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
    #22 0x7ff16c229e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f)
    #23 0x562a9a578474 in _start (/home/runner/work/Qarminer/Qarminer/godot.linuxbsd.editor.dev.x86_64.san+0x403b8474)
0x60e001451c40 is located 0 bytes to the right of 160-byte region [0x60e001451ba0,0x60e001451c40)
allocated by thread T0 here:
    #0 0x7ff16ceb4887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x562ab5ccd559 in Memory::alloc_static(unsigned long, bool) core/os/memory.cpp:75
    #2 0x562a9b353587 in Error CowData<float>::resize<false>(long) core/templates/cowdata.h:340
    #3 0x562a9b3400fe in Vector<float>::resize(long) core/templates/vector.h:95
    #4 0x562ab720600e in VariantConstructorFromArray<Vector<float> >::validated_construct(Variant*, Variant const**) core/variant/variant_construct.h:560
    #5 0x562a9c37a1fb in GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) modules/gdscript/gdscript_vm.cpp:1622
    #6 0x562a9bc01a8d in GDScriptInstance::callp(StringName const&, Variant const**, int, Callable::CallError&) modules/gdscript/gdscript.cpp:2006
    #7 0x562aa9e83a4a in bool Node::_gdvirtual__process_call<false>(double) scene/main/node.h:351
    #8 0x562aa9db1199 in Node::_notification(int) scene/main/node.cpp:55
    #9 0x562a9b25fedf in Node::_notificationv(int, bool) scene/main/node.h:50
    #10 0x562ab7865472 in Object::notification(int, bool) core/object/object.cpp:903
    #11 0x562aa9fbe4a4 in SceneTree::_process_group(SceneTree::ProcessGroup*, bool) scene/main/scene_tree.cpp:962
    #12 0x562aa9fc1740 in SceneTree::_process(bool) scene/main/scene_tree.cpp:1039
    #13 0x562aa9fb06cb in SceneTree::process(double) scene/main/scene_tree.cpp:526
    #14 0x562a9a8a3dca in Main::iteration() main/main.cpp:4052
    #15 0x562a9a599bb1 in OS_LinuxBSD::run() platform/linuxbsd/os_linuxbsd.cpp:962
    #16 0x562a9a5789ff in main platform/linuxbsd/godot_linuxbsd.cpp:85
    #17 0x7ff16c229d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
SUMMARY: AddressSanitizer: heap-buffer-overflow drivers/gles3/storage/mesh_storage.cpp:1826 in GLES3::MeshStorage::multimesh_instance_get_transform_2d(RID, int) const
Shadow bytes around the buggy address:
  0x0c1c80282330: fd fd fd fd fa fa fa fa fa fa fa fa fd fd fd fd
  0x0c1c80282340: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c1c80282350: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c1c80282360: 00 00 00 00 00 00 00 00 00 00 00 00 fa fa fa fa
  0x0c1c80282370: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c1c80282380: 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa fa fa
  0x0c1c80282390: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c1c802823a0: fd fd fd fd fa fa fa fa fa fa fa fa fd fd fd fd
  0x0c1c802823b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c1c802823c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c1c802823d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==22835==ABORTING

This example was found by Godot fuzzer - Qarminer, so it is quite unlikelly that this code could be used in real project, but still this should be handled gracefully.

Memory leaks or asan backtraces are visible when using Godot build with sanitizers support - https://github.com/qarmin/GodotBuilds/actions (linux -> linux-editor-sanitizers)

Steps to reproduce

Above

Minimal reproduction project (MRP)

Above

@clayjohn
Copy link
Member

I can't reproduce with bd2300d. For me the ERROR: Condition "p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)" is true. error prints endlessly, but there is no crash.

@akien-mga
Copy link
Member

akien-mga commented May 17, 2024

Did you compile with asan?

@qarmin Could you include your build command in such reports? Asan crashes can only be reproduced with an asan build and that's not clear from the current format of your reports.

@clayjohn
Copy link
Member

clayjohn commented May 17, 2024

I didn't realize that this was only a crash in asan builds. I just built a normal debug build

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants