bepaald / signalbackup-tools

Tool to work with Signal Backup files.
GNU General Public License v3.0
755 stars 36 forks source link

Core dumped when trying to export html #208

Closed trougnouf closed 4 months ago

trougnouf commented 4 months ago

I get the following error when trying to export html. The processing starts but crashes before all logs are exported.

[trougnouf@sd PhoneBak]$ signalbackup-tools Signal/signal-2024-04-25-04-00-00.backup (redacted) --exporthtml Signal_decoded_html
 *** Starting log: 2024-04-25 11:44:25 *** 
signalbackup-tools (signalbackup-tools) source version 20240424.090152
BACKUPFILE VERSION: 1
BACKUPFILE SIZE: 1409063424
COUNTER: 932266755
Reading backup file: 100.0%... done!
Database version: 223
Dealing with thread 1
Dealing with thread 2
Dealing with thread 3
Dealing with thread 4
Dealing with thread 5
Dealing with thread 6
Dealing with thread 7
Dealing with thread 8
Dealing with thread 9
Dealing with thread 10
Dealing with thread 11
Dealing with thread 12
Dealing with thread 13
Dealing with thread 14
Dealing with thread 15
Dealing with thread 16
Dealing with thread 17
Dealing with thread 18
Dealing with thread 19
Dealing with thread 20
Dealing with thread 21
Dealing with thread 22
Dealing with thread 23
Dealing with thread 24
Dealing with thread 25
Dealing with thread 26
Dealing with thread 27
Dealing with thread 28
Dealing with thread 29
Dealing with thread 30
Dealing with thread 31
Dealing with thread 32
Dealing with thread 33
Dealing with thread 34
Dealing with thread 35
Dealing with thread 36
Dealing with thread 37
Dealing with thread 38
Dealing with thread 39
Dealing with thread 40
Dealing with thread 41
Dealing with thread 42
Dealing with thread 43
Dealing with thread 44
Dealing with thread 45
Dealing with thread 46
Dealing with thread 47
Dealing with thread 48
Dealing with thread 49
Dealing with thread 50
Dealing with thread 51
Dealing with thread 52
Dealing with thread 53
Dealing with thread 54
Dealing with thread 55
Dealing with thread 56
Dealing with thread 57
Dealing with thread 58
Dealing with thread 59
Dealing with thread 60
Dealing with thread 61
Dealing with thread 62
Dealing with thread 63
Dealing with thread 64
Dealing with thread 65
Dealing with thread 66
Dealing with thread 67
Dealing with thread 68
Dealing with thread 69
Dealing with thread 70
Dealing with thread 71
Dealing with thread 72
Dealing with thread 73
Dealing with thread 74
Dealing with thread 75
Dealing with thread 76
Dealing with thread 77
Dealing with thread 78
Dealing with thread 79
/usr/include/c++/13.2.1/bits/basic_string.h:1341: constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::const_reference std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::back() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; const_reference = const char&]: Assertion '!empty()' failed.
Aborted (core dumped)

Using Arch Linux with signalbackup-tools-git 20240424.r0.g20c47ad-1, sqlite 3.45.2, openssl 3.2.1

(The backup file weighs 1.4 GB. There is no issue with regular database exports.)

trougnouf commented 4 months ago

Here is the backtrace:

(gdb) bt
#0  0x00007d2e3c1bf32c in ?? () from /usr/lib/libc.so.6
#1  0x00007d2e3c16e6c8 in raise () from /usr/lib/libc.so.6
#2  0x00007d2e3c1564b8 in abort () from /usr/lib/libc.so.6
#3  0x00007d2e3c4dd3b2 in std::__glibcxx_assert_fail (file=file@entry=0x5b5b6e58c490 "/usr/include/c++/13.2.1/bits/basic_string.h", line=line@entry=1341, 
    function=function@entry=0x5b5b6e58f2c0 "constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::const_reference std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::back() const [with _CharT = char; _Traits = std::char_traits<char>; "..., 
    condition=condition@entry=0x5b5b6e574629 "!empty()") at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/debug.cc:61
#4  0x00005b5b6e2eae20 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::back (this=0x7ffd9d1d04b0) at /usr/include/c++/13.2.1/bits/basic_string.h:1339
#5  std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::back (this=0x7ffd9d1d04b0) at /usr/include/c++/13.2.1/bits/basic_string.h:1339
#6  Base64::base64StringToBytes (str="") at signalbackup/../headerframe/../base64/base64.h:63
#7  0x00005b5b6e4e60c6 in ProtoBufParser<ProtoBufParser<unsigned char*, unsigned int, ProtoBufParser<ProtoBufParser<unsigned char*, unsigned int, std::vector<ProtoBufParser<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned char*, unsigned int>, bool>, std::allocator<ProtoBufParser<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned char*, unsigned int>, bool> > >, std::vector<ProtoBufParser<unsigned char*>, std::allocator<ProtoBufParser<unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, int>, std::allocator<ProtoBufParser<unsigned char*, int> > >, std::vector<ProtoBufParser<unsigned char*, unsigned char*, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, unsigned char*, unsigned char*> > >, std::vector<ProtoBufParser<ProtoBufParser<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned char*, unsigned int>, unsigned char*, unsigned long> >, std::allocator<ProtoBufParser<ProtoBufParser<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned char*, unsigned int>, unsigned char*, unsigned long> > > >, std::vector<ProtoBufParser<unsigned char*>, std::allocator<ProtoBufParser<unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, unsigned char*, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, unsigned char*, unsigned char*> > >, ProtoBufParser<unsigned char*>, ProtoBufParser<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ProtoBufParser<unsigned char*>, ProtoBufParser<>, ProtoBufParser<>, ProtoBufParser<>, std::vector<ProtoBufParser<ProtoBufParser<unsigned char*, unsigned char*, unsigned char*, unsigned long> >, std::allocator<ProtoBufParser<ProtoBufParser<unsigned char*, unsigned char*, unsigned char*, unsigned long> > > >, std::vector<ProtoBufParser<unsigned char*>, std::allocator<ProtoBufParser<unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, int>, std::allocator<ProtoBufParser<unsigned char*, int> > >, ProtoBufParser<unsigned char*>, ProtoBufParser<unsigned char*>, ProtoBufParser<bool>, std::vector<ProtoBufParser<ProtoBufParser<unsigned char*, unsigned long> >, std::allocator<ProtoBufParser<ProtoBufParser<unsigned char*, unsigned long> > > >, std::vector<ProtoBufParser<unsigned char*>, std::allocator<ProtoBufParser<unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, unsigned char*, unsigned char*, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, unsigned char*, unsigned char*, unsigned char*> > > >, unsigned char*, unsigned int> >, ProtoBufParser<unsigned char*, unsigned int, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*> > >, std::vector<unsigned char*, std::allocator<unsigned char*> >, std::vector<ProtoBufParser<unsigned char*, int>, std::allocator<ProtoBufParser<unsigned char*, int> > >, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned long, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned long, unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*> > >, ProtoBufParser<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ProtoBufParser<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ProtoBufParser<unsigned int>, int, int, int, std::vector<ProtoBufParser<unsigned char*, unsigned char*, int, unsigned long>, std::allocator<ProtoBufParser<unsigned char*, unsigned char*, int, unsigned long> > >, std::vector<unsigned char*, std::allocator<unsigned char*> >, std::vector<ProtoBufParser<unsigned char*, int>, std::allocator<ProtoBufParser<unsigned char*, int> > >, unsigned char*, ProtoBufParser<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, int, std::vector<ProtoBufParser<unsigned char*, unsigned long>, std::allocator<ProtoBufParser<unsigned char*, unsigned long> > >, std::vector<ProtoBufParser<unsigned char*, unsigned long>, std::allocator<ProtoBufParser<unsigned char*, unsigned long> > >, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*> > > >, ProtoBufParser<int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ProtoBufParser<unsigned int>, ProtoBufParser<int, int, int>, unsigned int, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned long, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned long, unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, unsigned char*, int, unsigned long>, std::allocator<ProtoBufParser<unsigned char*, unsigned char*, int, unsigned long> > >, unsigned char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::vector<ProtoBufParser<unsigned char*, unsigned long>, std::allocator<ProtoBufParser<unsigned char*, unsigned long> > > >, ProtoBufParser<int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ProtoBufParser<unsigned int>, ProtoBufParser<int, int, int>, unsigned int, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, int, unsigned int, unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned long, unsigned char*>, std::allocator<ProtoBufParser<unsigned char*, int, unsigned char*, unsigned long, unsigned char*> > >, std::vector<ProtoBufParser<unsigned char*, unsigned char*, int, unsigned long>, std::allocator<ProtoBufParser<unsigned char*, unsigned char*, int, unsigned long> > >, unsigned char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::vector<ProtoBufParser<unsigned char*, unsigned long>, std::allocator<ProtoBufParser<unsigned char*, unsigned long> > > > >::ProtoBufParser(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (base64="", this=0x7ffd9d1d0260) at signalbackup/../protobufparser/protobufparser.h:302
#8  SignalBackup::getGroupUpdateRecipients (this=this@entry=0x5b5b705e17a0, thread=<optimized out>, thread@entry=79) at signalbackup/getgroupupdaterecipients.cc:43
#9  0x00005b5b6e37b5c1 in SignalBackup::getAllThreadRecipients (this=this@entry=0x5b5b705e17a0, t=t@entry=79) at signalbackup/getallthreadrecipients.cc:81
#10 0x00005b5b6e48837c in SignalBackup::exportHtml (this=this@entry=0x5b5b705e17a0, directory="Signal_decoded_html", limittothreads=std::vector of length 0, capacity 0, daterangelist=std::vector of length 0, capacity 0, split=<optimized out>, selfphone="", calllog=<optimized out>, 
    searchpage=<optimized out>, stickerpacks=<optimized out>, migrate=<optimized out>, overwrite=<optimized out>, append=<optimized out>, lighttheme=<optimized out>, themeswitching=<optimized out>, addexportdetails=<optimized out>, blocked=<optimized out>, fullcontacts=<optimized out>, 
    settings=<optimized out>) at signalbackup/exporthtml.cc:278
#11 0x00005b5b6e289d87 in main (argc=<optimized out>, argv=<optimized out>) at arg/arg.h:631
bepaald commented 4 months ago

Thank you so much for your report.

I believe I have fixed the actual crash, but on investigating there is some more work to be done. The crash happened because a function was unexpectedly passed an empty string (it should now properly deal with this situation). It turns out the data that should be passed has moved from one place in the sql table to another. So while the crash should be fixed, there will now temporarily be some unhandled group-update-messages (in thread 79 in your case). I will need a little more time for that. I'll update here when I think things should be working.

bepaald commented 4 months ago

I had a go at this. The solution I went with is slightly hacky internally (I convert the new data into the old, so I can pass it to the existing functions), it's not unthinkable that it will fail sometime in the future if/when Signal makes changes to the new format that cause trouble when converting. But for now, as far as I can tell, it works.

Could you let me know if it works for you? No crashes or unexpected errors/warnings? Does the HTML look ok? If I remember correctly, basically all status message should have some output (a meaningful message, and an icon), so no unstyled 'Group V2 update' messages should exist (except possibly on the index page).

Thanks again for your thorough report, it was helpful.

trougnouf commented 4 months ago

It works and looks great, thank you! :)

I don't see any "Group V2 update" message anywhere or anything that looks off.

bepaald commented 4 months ago

That's great to hear, thanks for reporting back!