Skip to content

Crash undoing actions from a script #3539

@dacap

Description

@dacap

Source: https://community.aseprite.org/t/undo-crashes-aseprite-when-using-my-script/15828

Crash:

=================================================================
==12941==ERROR: AddressSanitizer: heap-use-after-free on address 0x60b00127dab0 at pc 0x5629ee74a707 bp 0x7ffc00dbeab0 sp 0x7ffc00dbeaa0
READ of size 8 at 0x60b00127dab0 thread T0
    #0 0x5629ee74a706 in app::Cmd::memSize() const src/app/cmd.cpp:89
    #1 0x5629ede8e4ea in app::DocUndo::undo() src/app/doc_undo.cpp:112
    #2 0x5629ee888780 in app::UndoCommand::onExecute(app::Context*) src/app/commands/cmd_undo.cpp:127
    #3 0x5629eddca165 in app::Command::execute(app::Context*) src/app/commands/command.cpp:74
    #4 0x5629ede389ca in app::Context::executeCommand(app::Command*, app::Params const&) src/app/context.cpp:168
    #5 0x5629ede378aa in app::Context::executeCommandFromMenuOrShortcut(app::Command*, app::Params const&) src/app/context.cpp:137
    #6 0x5629ee1cb364 in app::CustomizedGuiManager::onProcessMessage(ui::Message*) src/app/modules/gui.cpp:592
    #7 0x5629eed01409 in ui::Widget::sendMessage(ui::Message*) src/ui/widget.cpp:1263
    #8 0x5629eeca0622 in ui::Manager::sendMessageToWidget(ui::Message*, ui::Widget*) src/ui/manager.cpp:1603
    #9 0x5629eeca1021 in ui::Manager::pumpQueue() src/ui/manager.cpp:1468
    #10 0x5629eeca1674 in ui::Manager::dispatchMessages() src/ui/manager.cpp:718
    #11 0x5629eecbe88a in ui::MessageLoop::pumpMessages() src/ui/message_loop.cpp:26
    #12 0x5629eec9b9a9 in ui::Manager::run() src/ui/manager.cpp:248
    #13 0x5629edd689d9 in app::App::run() src/app/app.cpp:518
    #14 0x5629edd63d6c in app_main(int, char**) src/main/main.cpp:148
    #15 0x5629eed2f50c in main laf/os/common/main.cpp:67
    #16 0x7fb25bc29d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
    #17 0x7fb25bc29e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f)
    #18 0x5629edd63974 in _start (/home/david/builds/aseprite-gcc/bin/aseprite+0x20d974)

0x60b00127dab0 is located 0 bytes inside of 112-byte region [0x60b00127dab0,0x60b00127db20)
freed by thread T0 here:
    #0 0x7fb25ccb722f in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:172
    #1 0x5629ee79a5e6 in app::CmdTransaction::~CmdTransaction() src/app/cmd_transaction.h:23
    #2 0x5629ee74a42b in app::Cmd::dispose() src/app/cmd.cpp:79
    #3 0x5629ef670442 in undo::UndoState::~UndoState() src/undo/undo_state.h:32
    #4 0x5629ef670442 in undo::UndoHistory::deleteState(undo::UndoState*) src/undo/undo_history.cpp:212
    #5 0x5629ef6704df in undo::UndoHistory::clearRedo() src/undo/undo_history.cpp:70
    #6 0x5629ede8e6b6 in app::DocUndo::clearRedo() src/app/doc_undo.cpp:139
    #7 0x5629ede8e75c in app::DocUndo::add(app::CmdTransaction*) src/app/doc_undo.cpp:57
    #8 0x5629ee01a986 in app::Transaction::commit() src/app/transaction.cpp:97
    #9 0x5629ee9f898c in app::Tx::commit() src/app/tx.h:57
    #10 0x5629ee9f898c in App_transaction src/app/script/app_object.cpp:140
    #11 0x5629ef786f6f in luaD_precall third_party/lua/ldo.c:532
    #12 0x5629ef7b73f6 in luaV_execute third_party/lua/lvm.c:1624
    #13 0x5629ef787587 in ccall third_party/lua/ldo.c:577
    #14 0x5629ef7877a9 in luaD_callnoyield third_party/lua/ldo.c:595
    #15 0x5629ef779fa1 in f_call third_party/lua/lapi.c:1031
    #16 0x5629ef784c2d in luaD_rawrunprotected third_party/lua/ldo.c:144
    #17 0x5629ef7882a8 in luaD_pcall third_party/lua/ldo.c:892
    #18 0x5629ef77e12c in lua_pcallk third_party/lua/lapi.c:1057
    #19 0x5629ee5c569b in call src/app/script/events_class.cpp:105
    #20 0x5629ee5c6071 in non-virtual thunk to app::script::(anonymous namespace)::SpriteEvents::onCurrentUndoStateChange(app::DocUndo*) (/home/david/builds/aseprite-gcc/bin/aseprite+0xa70071)
    #21 0x5629ede8ff7e in void obs::observers<app::DocUndoObserver>::notify_observers<app::DocUndo*>(void (app::DocUndoObserver::*)(app::DocUndo*), app::DocUndo*) src/observable/obs/observers.h:37
    #22 0x5629ede8e4e2 in void obs::observable<app::DocUndoObserver>::notify_observers<app::DocUndo*>(void (app::DocUndoObserver::*)(app::DocUndo*), app::DocUndo*) src/observable/obs/observable.h:33
    #23 0x5629ede8e4e2 in app::DocUndo::undo() src/app/doc_undo.cpp:110
    #24 0x5629ee888780 in app::UndoCommand::onExecute(app::Context*) src/app/commands/cmd_undo.cpp:127
    #25 0x5629eddca165 in app::Command::execute(app::Context*) src/app/commands/command.cpp:74
    #26 0x5629ede389ca in app::Context::executeCommand(app::Command*, app::Params const&) src/app/context.cpp:168
    #27 0x5629ede378aa in app::Context::executeCommandFromMenuOrShortcut(app::Command*, app::Params const&) src/app/context.cpp:137
    #28 0x5629ee1cb364 in app::CustomizedGuiManager::onProcessMessage(ui::Message*) src/app/modules/gui.cpp:592
    #29 0x5629eed01409 in ui::Widget::sendMessage(ui::Message*) src/ui/widget.cpp:1263
    #30 0x5629eeca0622 in ui::Manager::sendMessageToWidget(ui::Message*, ui::Widget*) src/ui/manager.cpp:1603
    #31 0x5629eeca1021 in ui::Manager::pumpQueue() src/ui/manager.cpp:1468
    #32 0x5629eeca1674 in ui::Manager::dispatchMessages() src/ui/manager.cpp:718

previously allocated by thread T0 here:
    #0 0x7fb25ccb61c7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
    #1 0x5629ee01a585 in app::Transaction::Transaction(app::Context*, app::Doc*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, app::Modification) src/app/transaction.cpp:50
    #2 0x5629ee8cdf57 in app::Tx::Tx(app::Context*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, app::Modification) src/app/tx.h:37
    #3 0x5629ee8cdf57 in app::ToolLoopImpl::ToolLoopImpl(app::Editor*, app::Site, app::Context*, app::ToolLoopParams&, bool) src/app/ui/editor/tool_loop_impl.cpp:430
    #4 0x5629ee8bdf7c in app::create_tool_loop(app::Editor*, app::Context*, app::tools::Pointer::Button, bool, bool) src/app/ui/editor/tool_loop_impl.cpp:777
    #5 0x5629ee34e5e9 in app::StandbyState::startDrawingState(app::Editor*, ui::MouseMessage const*, app::StandbyState::DrawingType, app::tools::Pointer const&) src/app/ui/editor/standby_state.cpp:646
    #6 0x5629ee364cb1 in app::StandbyState::onMouseDown(app::Editor*, ui::MouseMessage*) src/app/ui/editor/standby_state.cpp:344
    #7 0x5629ee2f30e6 in app::Editor::onProcessMessage(ui::Message*) src/app/ui/editor/editor.cpp:1866
    #8 0x5629ee2b5c12 in onProcessMessage src/app/ui/doc_view.cpp:166
    #9 0x5629eed01409 in ui::Widget::sendMessage(ui::Message*) src/ui/widget.cpp:1263
    #10 0x5629eeca0622 in ui::Manager::sendMessageToWidget(ui::Message*, ui::Widget*) src/ui/manager.cpp:1603
    #11 0x5629eeca1021 in ui::Manager::pumpQueue() src/ui/manager.cpp:1468
    #12 0x5629eeca1674 in ui::Manager::dispatchMessages() src/ui/manager.cpp:718
    #13 0x5629eecbe88a in ui::MessageLoop::pumpMessages() src/ui/message_loop.cpp:26
    #14 0x5629eec9b9a9 in ui::Manager::run() src/ui/manager.cpp:248
    #15 0x5629edd689d9 in app::App::run() src/app/app.cpp:518
    #16 0x5629edd63d6c in app_main(int, char**) src/main/main.cpp:148
    #17 0x5629eed2f50c in main laf/os/common/main.cpp:67
    #18 0x7fb25bc29d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)

Maybe related to this Sentry crash: https://sentry.io/share/issue/ed018013bd024f3bb4647f59649b7648/ (and probable other crashes)

The script can be reduced to:

local spr = app.activeSprite
if not spr then return end

spr.events:on("change", function()
 -- The problem here is that the change event can be received from a
 -- "undo" command, so we are modifying the sprite while we're undoing
 -- something
 spr:newLayer()
 app.refresh()
end)

The issue is that we're listening the "change" event and modifying the sprite on this event can change it when we're undoing another command (undo/redo call the change event too).

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions