godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.51k stars 21.26k forks source link

Memory leak when using `RichTextLabel.remove_line` #49571

Closed qarmin closed 2 years ago

qarmin commented 3 years ago

Godot version

4.0.dev.custom_build. e82a1113a

System information

Ubuntu 21.04 - Nvidia GTX 970, Gnome shell 3.38 X11

Issue description

Running this code

func _process(_delta):
    var q = RichTextLabel.new()
    q.parse_bbcode(".")
    q.remove_line(0)
    q.queue_free()
    get_tree().quit()

Cause this memory leak

Direct leak of 80 byte(s) in 1 object(s) allocated from:
    #0 0x7f7a45601c47 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x1554db93 in Memory::alloc_static(unsigned long, bool) core/os/memory.cpp:75
    #2 0x1554daa4 in operator new(unsigned long, char const*) core/os/memory.cpp:40
    #3 0xf603343 in RichTextLabel::add_text(String const&) scene/gui/rich_text_label.cpp:2173
    #4 0xf621c26 in RichTextLabel::append_bbcode(String const&) scene/gui/rich_text_label.cpp:2746
    #5 0xf62049a in RichTextLabel::parse_bbcode(String const&) scene/gui/rich_text_label.cpp:2716
    #6 0x4135f47 in void call_with_variant_args_ret_helper<__UnexistingClass, Error, String const&, 0ul>(__UnexistingClass*, Error (__UnexistingClass::*)(String const&), Variant const**, Variant&, Callable::CallError&, IndexSequence<0ul>) core/variant/binder_common.h:635
    #7 0x413178a in void call_with_variant_args_ret_dv<__UnexistingClass, Error, String const&>(__UnexistingClass*, Error (__UnexistingClass::*)(String const&), Variant const**, int, Variant&, Callable::CallError&, Vector<Variant> const&) core/variant/binder_common.h:440
    #8 0x412d49f in MethodBindTR<Error, String const&>::call(Object*, Variant const**, int, Callable::CallError&) core/object/method_bind.h:452
    #9 0x1673b57d in Object::call(StringName const&, Variant const**, int, Callable::CallError&) core/object/object.cpp:816
    #10 0x15f2efdf in Variant::call(StringName const&, Variant const**, int, Variant&, Callable::CallError&) core/variant/variant_call.cpp:981
    #11 0x75d0f59 in GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) modules/gdscript/gdscript_vm.cpp:1471
    #12 0x70c4e9b in GDScriptInstance::call(StringName const&, Variant const**, int, Callable::CallError&) modules/gdscript/gdscript.cpp:1487
    #13 0x167a9d9b in ScriptInstance::call(StringName const&, Variant const&, Variant const&, Variant const&, Variant const&, Variant const&) core/object/script_language.cpp:322
    #14 0xe8f40e5 in Node::_notification(int) scene/main/node.cpp:58
    #15 0x28a3eef in Node::_notificationv(int, bool) scene/main/node.h:45
    #16 0x36b294c in CanvasItem::_notificationv(int, bool) scene/main/canvas_item.h:164
    #17 0x10775f94 in Node2D::_notificationv(int, bool) scene/2d/node_2d.h:37
    #18 0x1673ba12 in Object::notification(int, bool) core/object/object.cpp:825
    #19 0xe9f40e3 in SceneTree::_notify_group_pause(StringName const&, int) scene/main/scene_tree.cpp:809
    #20 0xe9e71f9 in SceneTree::process(float) scene/main/scene_tree.cpp:443
    #21 0x21bba5a in Main::iteration() main/main.cpp:2495
    #22 0x205db4f in OS_LinuxBSD::run() platform/linuxbsd/os_linuxbsd.cpp:278
    #23 0x204e041 in main platform/linuxbsd/godot_linuxbsd.cpp:58
    #24 0x7f7a44684564 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x28564)

Indirect leak of 24 byte(s) in 1 object(s) allocated from:
    #0 0x7f7a45601c47 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x1554db93 in Memory::alloc_static(unsigned long, bool) core/os/memory.cpp:75
    #2 0x4119b57 in CowData<char32_t>::resize(int) core/templates/cowdata.h:286
    #3 0xa3f09ad in String::resize(int) core/string/ustring.h:215
    #4 0x1687c06c in String::operator+=(char32_t) core/string/ustring.cpp:563
    #5 0x757b6ba in GDScriptTokenizer::string() modules/gdscript/gdscript_tokenizer.cpp:924
    #6 0x7582771 in GDScriptTokenizer::scan() modules/gdscript/gdscript_tokenizer.cpp:1259
    #7 0x740113b in GDScriptParser::advance() modules/gdscript/gdscript_parser.cpp:417
    #8 0x7434375 in GDScriptParser::parse_precedence(GDScriptParser::Precedence, bool, bool) modules/gdscript/gdscript_parser.cpp:2032
    #9 0x743487f in GDScriptParser::parse_expression(bool, bool) modules/gdscript/gdscript_parser.cpp:2041
    #10 0x74231d9 in GDScriptParser::parse_statement() modules/gdscript/gdscript_parser.cpp:1530
    #11 0x741db93 in GDScriptParser::parse_suite(String const&, GDScriptParser::SuiteNode*, bool) modules/gdscript/gdscript_parser.cpp:1387
    #12 0x74198f4 in GDScriptParser::parse_function() modules/gdscript/gdscript_parser.cpp:1282
    #13 0x751538b in void GDScriptParser::parse_class_member<GDScriptParser::FunctionNode>(GDScriptParser::FunctionNode* (GDScriptParser::*)(), GDScriptParser::AnnotationInfo::TargetKind, String const&) modules/gdscript/gdscript_parser.cpp:725
    #14 0x7409f41 in GDScriptParser::parse_class_body() modules/gdscript/gdscript_parser.cpp:789
    #15 0x740538c in GDScriptParser::parse_program() modules/gdscript/gdscript_parser.cpp:606
    #16 0x74001f8 in GDScriptParser::parse(String const&, String const&, bool) modules/gdscript/gdscript_parser.cpp:388
    #17 0x70acf54 in GDScript::reload(bool) modules/gdscript/gdscript.cpp:813
    #18 0x72737de in GDScriptCache::get_full_script(String const&, Error&, String const&) modules/gdscript/gdscript_cache.cpp:211
    #19 0x70dd1f3 in ResourceFormatLoaderGDScript::load(String const&, String const&, Error*, bool, float*, ResourceFormatLoader::CacheMode) modules/gdscript/gdscript.cpp:2249
    #20 0x15b8bbaf in ResourceLoader::_load(String const&, String const&, String const&, ResourceFormatLoader::CacheMode, Error*, bool, float*) core/io/resource_loader.cpp:193
    #21 0x15b8d43d in ResourceLoader::_thread_load_function(void*) core/io/resource_loader.cpp:220
    #22 0x15b942a8 in ResourceLoader::load(String const&, String const&, ResourceFormatLoader::CacheMode, Error*) core/io/resource_loader.cpp:575
    #23 0x11a32c48 in ResourceLoaderText::load() scene/resources/resource_format_text.cpp:442
    #24 0x11a61552 in ResourceFormatLoaderText::load(String const&, String const&, Error*, bool, float*, ResourceFormatLoader::CacheMode) scene/resources/resource_format_text.cpp:1279
    #25 0x15b8bbaf in ResourceLoader::_load(String const&, String const&, String const&, ResourceFormatLoader::CacheMode, Error*, bool, float*) core/io/resource_loader.cpp:193
    #26 0x15b8d43d in ResourceLoader::_thread_load_function(void*) core/io/resource_loader.cpp:220
    #27 0x15b942a8 in ResourceLoader::load(String const&, String const&, ResourceFormatLoader::CacheMode, Error*) core/io/resource_loader.cpp:575
    #28 0x21b37cb in Main::start() main/main.cpp:2320
    #29 0x204df74 in main platform/linuxbsd/godot_linuxbsd.cpp:57

This example was found by fuzzer, so I don't recommend trying understand in what situation such code could be used in real project, because such situation probably doesn't exists.

Steps to reproduce

Above

Minimal reproduction project

No response

qarmin commented 3 years ago

Another leak


    var temp_variable = RichTextLabel.new()
    temp_variable.push_align(46)
    temp_variable.pop()
    temp_variable.remove_line(1)
    temp_variable.queue_free()