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 heap-use-after-free when changing 2D editor selection #102510

Merged
merged 1 commit into from
Feb 7, 2025

Conversation

timothyqiu
Copy link
Member

I encountered this crash when trying to reproduce the issue using the MRP from #102421 (open tree.tscn scene and select the tree node).

The crash occurred because the iterator becomes invalid after calling erase().

ASan Output
=================================================================
==45052==ERROR: AddressSanitizer: heap-use-after-free on address 0x504000adc2a8 at pc 0x580606d370f5 bp 0x7ffffd8d36d0 sp 0x7ffffd8d36c0
READ of size 8 at 0x504000adc2a8 thread T0
    #0 0x580606d370f4 in List<CanvasItem*, DefaultAllocator>::Element::next() core/templates/list.h:73
    #1 0x580606d35fd1 in List<CanvasItem*, DefaultAllocator>::Iterator::operator++() core/templates/list.h:175
    #2 0x580606cdfeb5 in CanvasItemEditor::_draw_selection() editor/plugins/canvas_item_editor_plugin.cpp:3662
    #3 0x580606ced623 in CanvasItemEditor::_draw_viewport() editor/plugins/canvas_item_editor_plugin.cpp:4039
    #4 0x580606d5b0a0 in void call_with_variant_args_helper<CanvasItemEditor>(CanvasItemEditor*, void (CanvasItemEditor::*)(), Variant const**, Callable::CallError&, IndexSequence<>) core/variant/binder_common.h:315
    #5 0x580606d59616 in void call_with_variant_args<CanvasItemEditor>(CanvasItemEditor*, void (CanvasItemEditor::*)(), Variant const**, int, Callable::CallError&) core/variant/binder_common.h:429
    #6 0x580606d5661e in CallableCustomMethodPointer<CanvasItemEditor, void>::call(Variant const**, int, Variant&, Callable::CallError&) const core/object/callable_method_pointer.h:105
    #7 0x58060d13b96c in Callable::callp(Variant const**, int, Variant&, Callable::CallError&) const core/variant/callable.cpp:57
    #8 0x58060d9688eb in Object::emit_signalp(StringName const&, Variant const**, int) core/object/object.cpp:1236
    #9 0x580607e6eeb4 in Node::emit_signalp(StringName const&, Variant const**, int) scene/main/node.cpp:4021
    #10 0x5806017d822f in Error Object::emit_signal<>(StringName const&) core/object/object.h:933
    #11 0x580607cede90 in CanvasItem::_redraw_callback() scene/main/canvas_item.cpp:145
    #12 0x580605b8d1b0 in void call_with_variant_args_helper<CanvasItem>(CanvasItem*, void (CanvasItem::*)(), Variant const**, Callable::CallError&, IndexSequence<>) core/variant/binder_common.h:315
    #13 0x580605b844e8 in void call_with_variant_args<CanvasItem>(CanvasItem*, void (CanvasItem::*)(), Variant const**, int, Callable::CallError&) core/variant/binder_common.h:429
    #14 0x580605b70584 in CallableCustomMethodPointer<CanvasItem, void>::call(Variant const**, int, Variant&, Callable::CallError&) const core/object/callable_method_pointer.h:105
    #15 0x58060d13b96c in Callable::callp(Variant const**, int, Variant&, Callable::CallError&) const core/variant/callable.cpp:57
    #16 0x58060d9510db in CallQueue::_call_function(Callable const&, Variant const*, int, bool) core/object/message_queue.cpp:220
    #17 0x58060d95198b in CallQueue::flush() core/object/message_queue.cpp:268
    #18 0x580607ef203b in SceneTree::process(double) scene/main/scene_tree.cpp:581
    #19 0x58060110dded in Main::iteration() main/main.cpp:4473
    #20 0x580600f001f9 in OS_LinuxBSD::run() platform/linuxbsd/os_linuxbsd.cpp:962
    #21 0x580600eeee82 in main platform/linuxbsd/godot_linuxbsd.cpp:85
    #22 0x7e6bfaf3d487  (/usr/lib/libc.so.6+0x27487) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #23 0x7e6bfaf3d54b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #24 0x580600eeea64 in _start (/home/timothy/repos/godot-master/bin/godot.linuxbsd.editor.dev.x86_64.san+0x978ba64) (BuildId: b02c386ad722d832153837246ba1ae0a2cb60b77)

0x504000adc2a8 is located 24 bytes inside of 48-byte region [0x504000adc290,0x504000adc2c0)
freed by thread T0 here:
    #0 0x7e6bfb2fc102 in free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x58060cafa85c in Memory::free_static(void*, bool) core/os/memory.cpp:199
    #2 0x580600ef05f9 in DefaultAllocator::free(void*) core/os/memory.h:97
    #3 0x580606a84216 in void memdelete_allocator<List<CanvasItem*, DefaultAllocator>::Element, DefaultAllocator>(List<CanvasItem*, DefaultAllocator>::Element*) core/os/memory.h:155
    #4 0x580606a8419f in List<CanvasItem*, DefaultAllocator>::_Data::erase(List<CanvasItem*, DefaultAllocator>::Element*) core/templates/list.h:249
    #5 0x580606a83e2b in List<CanvasItem*, DefaultAllocator>::erase(List<CanvasItem*, DefaultAllocator>::Element*) core/templates/list.h:437
    #6 0x580606d37cef in List<CanvasItem*, DefaultAllocator>::erase(CanvasItem* const&) core/templates/list.h:455
    #7 0x580606cdfea6 in CanvasItemEditor::_draw_selection() editor/plugins/canvas_item_editor_plugin.cpp:3664
    #8 0x580606ced623 in CanvasItemEditor::_draw_viewport() editor/plugins/canvas_item_editor_plugin.cpp:4039
    #9 0x580606d5b0a0 in void call_with_variant_args_helper<CanvasItemEditor>(CanvasItemEditor*, void (CanvasItemEditor::*)(), Variant const**, Callable::CallError&, IndexSequence<>) core/variant/binder_common.h:315
    #10 0x580606d59616 in void call_with_variant_args<CanvasItemEditor>(CanvasItemEditor*, void (CanvasItemEditor::*)(), Variant const**, int, Callable::CallError&) core/variant/binder_common.h:429
    #11 0x580606d5661e in CallableCustomMethodPointer<CanvasItemEditor, void>::call(Variant const**, int, Variant&, Callable::CallError&) const core/object/callable_method_pointer.h:105
    #12 0x58060d13b96c in Callable::callp(Variant const**, int, Variant&, Callable::CallError&) const core/variant/callable.cpp:57
    #13 0x58060d9688eb in Object::emit_signalp(StringName const&, Variant const**, int) core/object/object.cpp:1236
    #14 0x580607e6eeb4 in Node::emit_signalp(StringName const&, Variant const**, int) scene/main/node.cpp:4021
    #15 0x5806017d822f in Error Object::emit_signal<>(StringName const&) core/object/object.h:933
    #16 0x580607cede90 in CanvasItem::_redraw_callback() scene/main/canvas_item.cpp:145
    #17 0x580605b8d1b0 in void call_with_variant_args_helper<CanvasItem>(CanvasItem*, void (CanvasItem::*)(), Variant const**, Callable::CallError&, IndexSequence<>) core/variant/binder_common.h:315
    #18 0x580605b844e8 in void call_with_variant_args<CanvasItem>(CanvasItem*, void (CanvasItem::*)(), Variant const**, int, Callable::CallError&) core/variant/binder_common.h:429
    #19 0x580605b70584 in CallableCustomMethodPointer<CanvasItem, void>::call(Variant const**, int, Variant&, Callable::CallError&) const core/object/callable_method_pointer.h:105
    #20 0x58060d13b96c in Callable::callp(Variant const**, int, Variant&, Callable::CallError&) const core/variant/callable.cpp:57
    #21 0x58060d9510db in CallQueue::_call_function(Callable const&, Variant const*, int, bool) core/object/message_queue.cpp:220
    #22 0x58060d95198b in CallQueue::flush() core/object/message_queue.cpp:268
    #23 0x580607ef203b in SceneTree::process(double) scene/main/scene_tree.cpp:581
    #24 0x58060110dded in Main::iteration() main/main.cpp:4473
    #25 0x580600f001f9 in OS_LinuxBSD::run() platform/linuxbsd/os_linuxbsd.cpp:962
    #26 0x580600eeee82 in main platform/linuxbsd/godot_linuxbsd.cpp:85
    #27 0x7e6bfaf3d487  (/usr/lib/libc.so.6+0x27487) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #28 0x7e6bfaf3d54b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #29 0x580600eeea64 in _start (/home/timothy/repos/godot-master/bin/godot.linuxbsd.editor.dev.x86_64.san+0x978ba64) (BuildId: b02c386ad722d832153837246ba1ae0a2cb60b77)

previously allocated by thread T0 here:
    #0 0x7e6bfb2fd721 in malloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x58060caf9c86 in Memory::alloc_static(unsigned long, bool) core/os/memory.cpp:106
    #2 0x580600ef05da in DefaultAllocator::alloc(unsigned long) core/os/memory.h:96
    #3 0x58060caf99cb in operator new(unsigned long, void* (*)(unsigned long)) core/os/memory.cpp:43
    #4 0x580606d35a77 in List<CanvasItem*, DefaultAllocator>::push_back(CanvasItem* const&) core/templates/list.h:298
    #5 0x580606c98f15 in CanvasItemEditor::_get_edited_canvas_items(bool, bool, bool*) const editor/plugins/canvas_item_editor_plugin.cpp:813
    #6 0x580606cdc19c in CanvasItemEditor::_draw_selection() editor/plugins/canvas_item_editor_plugin.cpp:3553
    #7 0x580606ced623 in CanvasItemEditor::_draw_viewport() editor/plugins/canvas_item_editor_plugin.cpp:4039
    #8 0x580606d5b0a0 in void call_with_variant_args_helper<CanvasItemEditor>(CanvasItemEditor*, void (CanvasItemEditor::*)(), Variant const**, Callable::CallError&, IndexSequence<>) core/variant/binder_common.h:315
    #9 0x580606d59616 in void call_with_variant_args<CanvasItemEditor>(CanvasItemEditor*, void (CanvasItemEditor::*)(), Variant const**, int, Callable::CallError&) core/variant/binder_common.h:429
    #10 0x580606d5661e in CallableCustomMethodPointer<CanvasItemEditor, void>::call(Variant const**, int, Variant&, Callable::CallError&) const core/object/callable_method_pointer.h:105
    #11 0x58060d13b96c in Callable::callp(Variant const**, int, Variant&, Callable::CallError&) const core/variant/callable.cpp:57
    #12 0x58060d9688eb in Object::emit_signalp(StringName const&, Variant const**, int) core/object/object.cpp:1236
    #13 0x580607e6eeb4 in Node::emit_signalp(StringName const&, Variant const**, int) scene/main/node.cpp:4021
    #14 0x5806017d822f in Error Object::emit_signal<>(StringName const&) core/object/object.h:933
    #15 0x580607cede90 in CanvasItem::_redraw_callback() scene/main/canvas_item.cpp:145
    #16 0x580605b8d1b0 in void call_with_variant_args_helper<CanvasItem>(CanvasItem*, void (CanvasItem::*)(), Variant const**, Callable::CallError&, IndexSequence<>) core/variant/binder_common.h:315
    #17 0x580605b844e8 in void call_with_variant_args<CanvasItem>(CanvasItem*, void (CanvasItem::*)(), Variant const**, int, Callable::CallError&) core/variant/binder_common.h:429
    #18 0x580605b70584 in CallableCustomMethodPointer<CanvasItem, void>::call(Variant const**, int, Variant&, Callable::CallError&) const core/object/callable_method_pointer.h:105
    #19 0x58060d13b96c in Callable::callp(Variant const**, int, Variant&, Callable::CallError&) const core/variant/callable.cpp:57
    #20 0x58060d9510db in CallQueue::_call_function(Callable const&, Variant const*, int, bool) core/object/message_queue.cpp:220
    #21 0x58060d95198b in CallQueue::flush() core/object/message_queue.cpp:268
    #22 0x580607ef203b in SceneTree::process(double) scene/main/scene_tree.cpp:581
    #23 0x58060110dded in Main::iteration() main/main.cpp:4473
    #24 0x580600f001f9 in OS_LinuxBSD::run() platform/linuxbsd/os_linuxbsd.cpp:962
    #25 0x580600eeee82 in main platform/linuxbsd/godot_linuxbsd.cpp:85
    #26 0x7e6bfaf3d487  (/usr/lib/libc.so.6+0x27487) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #27 0x7e6bfaf3d54b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #28 0x580600eeea64 in _start (/home/timothy/repos/godot-master/bin/godot.linuxbsd.editor.dev.x86_64.san+0x978ba64) (BuildId: b02c386ad722d832153837246ba1ae0a2cb60b77)

SUMMARY: AddressSanitizer: heap-use-after-free core/templates/list.h:73 in List<CanvasItem*, DefaultAllocator>::Element::next()
Shadow bytes around the buggy address:
  0x504000adc000: fa fa 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
  0x504000adc080: fa fa 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
  0x504000adc100: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x504000adc180: fa fa fd fd fd fd fd fd fa fa 00 00 00 00 00 fa
  0x504000adc200: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
=>0x504000adc280: fa fa fd fd fd[fd]fd fd fa fa fa fa fa fa fa fa
  0x504000adc300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x504000adc380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x504000adc400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x504000adc480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x504000adc500: 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
==45052==ABORTING

@Repiteo Repiteo merged commit 29ded6b into godotengine:master Feb 7, 2025
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Feb 7, 2025

Thanks!

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

Successfully merging this pull request may close these issues.

4 participants