The Sacred Tears TRUE: Crash in savegame scene #556

Closed
fdelapena opened this Issue Sep 3, 2015 · 3 comments

Projects

None yet

2 participants

@fdelapena
Member

How to reproduce:

  • Download The Sacred Tears TRUE game demo and "fix" the LcfMapTree (game protection).
  • Play a bit until reaching the accessible game menu
  • Game menu -> Save game -> select a game file slot and save
  • Go to the main menu
  • Load game

Also reproducible while trying to access save scene. It crashes while trying to read some game slot data.

It works properly with generated RPG_RT savegames, so Player is creating corrupted savegames.

UPDATE: There is a workaround to save the game without issues, by adding the following 2 lines in the RPG_RT.ini:

[EasyRPG]
Encoding=932

Program crashes with:

src/ldb_eventcommand.cpp:151: static void RawStruct<std::vector<RPG::EventCommand> >::ReadLcf(std::vector<RPG::EventCommand>&, LcfReader&, uint32_t): Assertion `stream.Tell() == endpos' failed

Backtrace:

Program received signal SIGABRT, Aborted.
0x00007ffff2dad9c8 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:55
55    return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
#0  0x00007ffff2dad9c8 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:55
        resultvar = 0
        pid = 5964
        selftid = 5964
#1  0x00007ffff2daf65a in __GI_abort () at abort.c:89
        save_stage = 2
        act = {__sigaction_handler = {sa_handler = 0x4, sa_sigaction = 0x4}, 
          sa_mask = {__val = {4436966, 140737488344880, 140737488344768, 
              47244640256, 0, 0, 0, 21474836480, 140737269203742, 
              140737488344920, 140737488344720, 140737269215640, 
              140737269222720, 140737488344944, 140737353990144, 
              140737348645428}}, sa_flags = 151, 
          sa_restorer = 0x7ffff7ac3280 <RawStruct<std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> > >::ReadLcf(std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> >&, LcfReader&, unsigned int)::__PRETTY_FUNCTION__>}
        sigs = {__val = {32, 0 <repeats 15 times>}}
#2  0x00007ffff2da6187 in __assert_fail_base (fmt=<optimized out>, 
    assertion=assertion@entry=0x7ffff7ac3234 "stream.Tell() == endpos", 
    file=file@entry=0x7ffff7ac321b "src/ldb_eventcommand.cpp", 
    line=line@entry=151, 
    function=function@entry=0x7ffff7ac3280 <RawStruct<std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> > >::ReadLcf(std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> >&, LcfReader&, unsigned int)::__PRETTY_FUNCTION__> "static void RawStruct<std::vector<RPG::EventCommand> >::ReadLcf(std::vector<RPG::EventCommand>&, LcfReader&, uint32_t)") at assert.c:92
        str = 0x380fe00 "0\377\200\003"
        total = 4096
#3  0x00007ffff2da6232 in __GI___assert_fail (
    assertion=0x7ffff7ac3234 "stream.Tell() == endpos", 
    file=0x7ffff7ac321b "src/ldb_eventcommand.cpp", line=151, 
    function=0x7ffff7ac3280 <RawStruct<std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> > >::ReadLcf(std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> >&, LcfReader&, unsigned int)::__PRETTY_FUNCTION__> "static void RawStruct<std::vector<RPG::EventCommand> >::ReadLcf(std::vector<RPG::EventCommand>&, LcfReader&, uint32_t)") at assert.c:101
No locals.
#4  0x00007ffff792de82 in RawStruct<std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> > >::ReadLcf (
    event_commands=std::vector of length 313, capacity 512 = {...}, 
    stream=..., length=3416) at src/ldb_eventcommand.cpp:151
        startpos = 12062
        endpos = 15478
        __PRETTY_FUNCTION__ = "static void RawStruct<std::vector<RPG::EventCommand> >::ReadLcf(std::vector<RPG::EventCommand>&, LcfReader&, uint32_t)"
#5  0x00007ffff7a884d7 in TypeReader<std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> >, (Category::Index)3>::ReadLcf (
    ref=std::vector of length 313, capacity 512 = {...}, stream=..., 
    length=3416) at ./src/reader_struct.h:98
No locals.
#6  0x00007ffff7aac49e in TypedField<RPG::SaveEventCommands, std::vector<RPG::EventCommand, std::allocator<RPG::EventCommand> > >::ReadLcf (this=0x88f580, 
    obj=..., stream=..., length=3416) at ./src/reader_struct.h:363
No locals.
#7  0x00007ffff7958dc7 in Struct<RPG::SaveEventCommands>::ReadLcf (obj=..., 
    stream=...) at src/reader_struct.cpp:55
        it = {first = 2, second = }
        chunk_info = {ID = 2, length = 3416}
#8  0x00007ffff797fb08 in TypeReader<RPG::SaveEventCommands, (Category::Index)1>::ReadLcf (ref=..., stream=...) at src/reader_struct.h:534
No locals.
#9  0x00007ffff795932b in Struct<RPG::SaveEventCommands>::ReadLcf (
    vec=std::vector of length 1, capacity 1 = {...}, stream=...)
    at src/reader_struct.cpp:189
        i = 0
        count = 1
#10 0x00007ffff7aad6ee in TypeReader<std::vector<RPG::SaveEventCommands, std::allocator<RPG::SaveEventCommands> >, (Category::Index)1>::ReadLcf (
    ref=std::vector of length 1, capacity 1 = {...}, stream=...)
    at ./src/reader_struct.h:556
No locals.
#11 0x00007ffff7aae3a2 in TypedField<RPG::SaveEvents, std::vector<RPG::SaveEventCommands, std::allocator<RPG::SaveEventCommands> > >::ReadLcf (this=0x88fa60, 
    obj=..., stream=..., length=3430) at ./src/reader_struct.h:363
No locals.
#12 0x00007ffff795a093 in Struct<RPG::SaveEvents>::ReadLcf (obj=..., 
    stream=...) at src/reader_struct.cpp:55
        it = {first = 1, second = }
        chunk_info = {ID = 1, length = 3430}
#13 0x00007ffff7980872 in TypeReader<RPG::SaveEvents, (Category::Index)1>::ReadLcf (ref=..., stream=...) at src/reader_struct.h:534
No locals.
#14 0x00007ffff7aa92ac in TypedField<RPG::Save, RPG::SaveEvents>::ReadLcf (
    this=0x88f4f0, obj=..., stream=..., length=3437)
    at ./src/reader_struct.h:363
No locals.
#15 0x00007ffff795728b in Struct<RPG::Save>::ReadLcf (obj=..., stream=...)
    at src/reader_struct.cpp:55
        it = {first = 113, second = }
        chunk_info = {ID = 113, length = 3437}
#16 0x00007ffff79374fe in LSD_Reader::Load (filename="./Save01.lsd", 
    encoding="ibm-5348_P100-1997") at src/lsd_reader.cpp:45
        reader = {filename = "./Save01.lsd", encoding = "ibm-5348_P100-1997", 
          stream = 0x2b27c90, static error_str = ""}
        header = "LcfSaveData"
        save = 0x2b27ec0
#17 0x000000000053f9ca in Scene_File::Start (this=0x2ce38c0)
    at src/scene_file.cpp:70
        savegame = {_M_ptr = 0x865ff0 <Input::triggered>}
        w = {px = 0x2b27700, pn = {pi_ = 0x30d8a70}}
        ss = 
    {<std::basic_iostream<char, std::char_traits<char> >> = {<std::basic_istream<char, std::char_traits<char> >> = {<std::basic_ios<char, std::char_traits<char> >> = {<std::ios_base> = {
                  _vptr.ios_base = 0x7ffff39cf010 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+104>, 
                  static boolalpha = std::_S_boolalpha, 
                  static dec = std::_S_dec, static fixed = std::_S_fixed, 
                  static hex = std::_S_hex, 
                  static internal = std::_S_internal, 
                  static left = std::_S_left, static oct = std::_S_oct, 
                  static right = std::_S_right, 
                  static scientific = std::_S_scientific, 
                  static showbase = std::_S_showbase, 
                  static showpoint = std::_S_showpoint, 
                  static showpos = std::_S_showpos, 
                  static skipws = std::_S_skipws, 
                  static unitbuf = std::_S_unitbuf, 
                  static uppercase = std::_S_uppercase, 
                  static adjustfield = std::_S_adjustfield, 
                  static basefield = std::_S_basefield, 
                  static floatfield = std::_S_floatfield, 
                  static badbit = std::_S_badbit, 
                  static eofbit = std::_S_eofbit, 
                  static failbit = std::_S_failbit, 
                  static goodbit = std::_S_goodbit, static app = std::_S_app, 
                  static ate = std::_S_ate, static binary = std::_S_bin, 
                  static in = std::_S_in, static out = std::_S_out, 
                  static trunc = std::_S_trunc, static beg = std::_S_beg, 
                  static cur = std::_S_cur, static end = std::_S_end, 
                  _M_precision = 6, _M_width = 0, _M_flags = 4098, 
                  _M_exception = std::_S_goodbit, 
                  _M_streambuf_state = std::_S_goodbit, _M_callbacks = 0x0, 
                  _M_word_zero = {_M_pword = 0x0, _M_iword = 0}, 
                  _M_local_word = {{_M_pword = 0x0, _M_iword = 0}, {
                      _M_pword = 0x0, _M_iword = 0}, {_M_pword = 0x0, 
                      _M_iword = 0}, {_M_pword = 0x0, _M_iword = 0}, {
                      _M_pword = 0x0, _M_iword = 0}, {_M_pword = 0x0, 
                      _M_iword = 0}, {_M_pword = 0x0, _M_iword = 0}, {
                      _M_pword = 0x0, _M_iword = 0}}, _M_word_size = 8, 
                  _M_word = 0x7fffffffdd18, _M_ios_locale = {static none = 0, 
                    static ctype = 1, static numeric = 2, static collate = 4, 
                    static time = 8, static monetary = 16, 
                    static messages = 32, static all = 63, 
                    _M_impl = 0x7ffff39d8860 <(anonymous namespace)::c_locale_impl>, 
                    static _S_classic = 0x7ffff39d8860 <(anonymous namespace)::c_locale_impl>, 
                    static _S_global = 0x7ffff39d8860 <(anonymous namespace)::c_locale_impl>, 
                    static _S_categories = 0x7ffff39cb1e0 <__gnu_cxx::category_names>, static _S_once = 2}}, _M_tie = 0x0, _M_fill = 32 ' ', _M_fill_init = true, 
                _M_streambuf = 0x7fffffffdc88, 
                _M_ctype = 0x7ffff39d8280 <(anonymous namespace)::ctype_c>, 
                _M_num_put = 0x7ffff39d8210 <(anonymous namespace)::num_put_c>, _M_num_get = 0x7ffff39d8220 <(anonymous namespace)::num_get_c>}, 
              _vptr.basic_istream = 0x7ffff39cefc0 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+24>, 
              _M_gcount = 0}, <std::basic_ostream<char, std::char_traits<char> >> = {
              _vptr.basic_ostream = 0x7ffff39cefe8 <vtable for std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >+64>}, <No data fields>}, 
          _M_stringbuf = {<std::basic_streambuf<char, std::char_traits<char> >> = {
              _vptr.basic_streambuf = 0x7ffff39cec50 <vtable for std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >+16>, 
              _M_in_beg = 0x2b27a18 "Save01.lsd 1", 
              _M_in_cur = 0x2b27a18 "Save01.lsd 1", 
              _M_in_end = 0x2b27a19 "ave01.lsd 1", 
              _M_out_beg = 0x2b27a18 "Save01.lsd 1", 
              _M_out_cur = 0x2b27a22 " 1", 
              _M_out_end = 0x2b27c18 "\350d\262\002", _M_buf_locale = {
                static none = 0, static ctype = 1, static numeric = 2, 
                static collate = 4, static time = 8, static monetary = 16, 
                static messages = 32, static all = 63, 
                _M_impl = 0x7ffff39d8860 <(anonymous namespace)::c_locale_impl>, static _S_classic = 0x7ffff39d8860 <(anonymous namespace)::c_locale_impl>, 
                static _S_global = 0x7ffff39d8860 <(anonymous namespace)::c_locale_impl>, static _S_categories = 0x7ffff39cb1e0 <__gnu_cxx::category_names>, 
                static _S_once = 2}}, _M_mode = (std::_S_in | std::_S_out), 
            _M_string = "S"}}
        file = "./Save01.lsd"
        i = 0
#18 0x0000000000456266 in Scene::MainFunction (this=0x2ce38c0)
    at src/scene.cpp:78
        init = false
        __PRETTY_FUNCTION__ = "virtual void Scene::MainFunction()"
#19 0x000000000043dc53 in Player::MainLoop () at src/player.cpp:178
No locals.
#20 0x000000000043dbdc in Player::Run () at src/player.cpp:173
No locals.
#21 0x0000000000431f15 in main (argc=2, argv=0x7fffffffe028)
    at src/platform/sdl_main.cpp:31
No locals.
@fdelapena fdelapena changed the title from Assertion failed "stream.Tell() == endpos" when loading a savegame to Assertion failed "stream.Tell() == endpos" when accessing savegame scene Sep 3, 2015
@fdelapena fdelapena changed the title from Assertion failed "stream.Tell() == endpos" when accessing savegame scene to The Sacred Tears TRUE: Assertion failed "stream.Tell() == endpos" in savegame scene Sep 8, 2015
@fdelapena fdelapena changed the title from The Sacred Tears TRUE: Assertion failed "stream.Tell() == endpos" in savegame scene to The Sacred Tears TRUE: Crash in savegame scene Sep 8, 2015
@Ghabry
Member
Ghabry commented Nov 7, 2015

I can't reproduce this crash anymore after doing a full recompile of liblcf.
There is one obvious bug in the savegame writer... but even with that bug it doesn't crash.

All new saves don't crash

@fdelapena
Member

Still crashes for me, after a full rebuild of liblcf and player, but I have found a possible reason:

When using automatic encoding detection, it might be saving with some invalid string size, then it crashes. This game has not been fully translated and at least internal strings from the lmt tree contains mojibake. When using --encoding 932 and saving game won't crash when accesing the savegame scene.

Attached 2 savegames: Save02.lsd saved with --encoding 932 and Save03 saved with automatic encoding (Western).
issue556.zip

There are very few differences when compared with a binary diff tool (e.g. vbindiff or ExamDiff Pro), with lcf2xml should be easier to check but liblcf will fail in the same assertion.

If you leave Save03 in the game folder, it will crash even when trying to play with --encoding 932.

@Ghabry
Member
Ghabry commented Dec 18, 2015

Sounds like a liblcf bug? Would be probably nice to get fixed before 0.4. Will give it a try on Monday. But sounds like some work and reader_struct will be involved ugh

Maybe ICU has a function to drop invalid codepoints instead of returning the original.

@Ghabry Ghabry added this to the 0.4 milestone Dec 18, 2015
@fdelapena fdelapena modified the milestone: 0.4.1, 0.4 Dec 23, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment