koreader / crengine

This is the KOReader CREngine fork. It cross-pollinates with the official CoolReader repository at https://github.com/buggins/coolreader, in case you were looking for that one.
70 stars 45 forks source link

Crash in ldomXPointer::getRect #481

Closed NiLuJe closed 2 years ago

NiLuJe commented 2 years ago

c.f., https://www.mobileread.com/forums/showthread.php?t=347071 for the test-case (in my case, paging back from the top of the second page (specifically, on xkrvc) after the mentioned chapter did the trick).

#0  0x34665642 in ldomXPointer::getRect (this=this@entry=0x7ee2ad00, rect=..., extended=<optimized out>, adjusted=adjusted@entry=false) at /var/tmp/niluje/Build_KO/koreader/base/thirdparty/kpvcrlib/crengine/crengine/src/lvtinydom.cpp:9634
9634    /var/tmp/niluje/Build_KO/koreader/base/thirdparty/kpvcrlib/crengine/crengine/src/lvtinydom.cpp: No such file or directory.
#0  0x34665642 in ldomXPointer::getRect (this=this@entry=0x7ee2ad00, rect=..., extended=<optimized out>, adjusted=adjusted@entry=false) at /var/tmp/niluje/Build_KO/koreader/base/thirdparty/kpvcrlib/crengine/crengine/src/lvtinydom.cpp:9634
        w = {59800, 12722, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 10, 42928, 32482, 0, 0, 43132, 32482, 41708, 10959, 45120, 11286, 42960, 32482, 6635, 2, 748, 0, 14477, 3, 43132, 32482, 7679, 65535, 41912, 10959, 43000, 32482, 32768, 0, 32813, 0, 64192, 65535, 21751, 3, 5, 0, 16072, 11276, 45120, 11282, 45120, 11286, 1, 0, 0, 0, 0, 0, 0, 
          0, 577, 1023, 39216, 10961, 43132, 32482, 11, 0, 43056, 32482, 0, 0, 0, 9, 43056, 32482, 79, 0, 11, 0, 43132, 32482, 11, 0, 43080, 32482, 6369, 2, 32766, 0, 2048, 0, 43132, 32482, 43132, 32482, 41912, 10959, 43104, 32482, 0, 0, 43132, 32482, 41912, 10959, 43120, 32482, 43128, 32482, 22735, 3, 0, 0, 0, 0, 1, 1, 9, 0, 32767, 65535, 32769, 32769, 
          32772, 32772, 32770, 32770, 7, 7, 32764, 32764, 32768, 32768, 32762, 32762, 11, 11, 32747, 32747, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 46412, 127, 33032, 127, 16088, 11272, 41912, 10959, 8191, 
          65535...}
        flg = "\000`\317*\002\000\000\000\020\321\325\062h\347\030>\230\245\342~\274g\317*\b\000\000\000\274g\317*\b\000\000\000\001\000\000\000\340\245\342~\001\000\000\000\000\000\000\000\250\246\342~ܥ\342~\260:\302*\002\000\000\000\000\000\000\000\002\000\000\000,\246\342~|\000\000\000w\000\000\000n\000\000\000[\000\000\000:", '\000' <repeats 19 times>, "\002\000\000\000\021\000\000\000\200\000\000\000\000`\317*\021\000\000\000T\020\315*(b\317*\314چ4\000\000\000\000\000Ѕ4\274g\317*\200\000\000\000\000\000\000\000p\246\342~\b\000\000\000\001\000\000\000\260\325\325\062\\\246\342~\260:\302*\220\001\263\061\000\000\000\000\000\000\000\000"...
        str = {pchunk = 0x33fef1b0, static EMPTY_STR_32 = 0x3486dacc <empty_chunk_32>, static empty_str = {pchunk = 0x3486dacc <empty_chunk_32>, static EMPTY_STR_32 = 0x3486dacc <empty_chunk_32>, static empty_str = <same as static member of an already seen type>}}
        chx = <optimized out>
        font = 0x40100
        hints = 0
        word = 0x31b28da8
        word_is_rtl = <optimized out>
        lastWord = false
        w = <optimized out>
        frmline = 0x31b28d70
        line_is_bidi = false
        l = <optimized out>
        fmt = {<lvdomElementFormatRec> = {_y = 1273, _height = 1005, _x = 0, _width = 1050, _inner_width = 1050, _inner_x = 0, _inner_y = 0, _baseline = 0, _usable_left_overflow = 15, _usable_right_overflow = 15, _top_overflow = 0, _bottom_overflow = 0, _lang_node_idx = 2241, _flags = 40, _extra0 = 0, _extra1 = 0, _extra2 = 0, _extra3 = 0, _extra4 = 0, 
            _extra5 = 0, _listprop_node_idx = 0}, _node = 0x32d5d5b0, _modified = false, _dirty = false}
        inner_width = <optimized out>
        xp = {<ldomXPointer> = {_data = 0x3e12b4c0}, _indexes = {0, 0, 6, 0, 0, 0, 2, 1, 3, 3247168, 726639851, 2, 1, 852914104, 973102656, 2128782544, 726640423, 2, 0, 0, 2128782552, 2128784548, 0, 1041381048, 879563173, 2128782584, 128, 2128783316, 726640447, 0, 879563173, 852913664, 852909568, 3, 16, 718233600, 3, 872919600, 2128782624, 61, 879025173, 
            881184768, 718235580, 16, 760, 2128782712, 881184768, 1, 718233600, 2128782692, 0, 852909568, 0, 0, 1441804, 0, 1441804, 2128782696, 878994269, 0, 1441804, 2, 8, 2}, _level = 9}
        bestBidiRect = {left = 0, top = 0, right = 0, bottom = 0}
        rc = {left = 6, top = 8993, right = 1056, bottom = 9998}
        srcLen = 1005
        lastOffset = <optimized out>
        nearestForwardSrcIndex = <optimized out>
        hasBestBidiRect = 26
        node = 0x0
        srcIndex = <optimized out>
        lastLen = <optimized out>
        txtform = {_ptr = 0x317458}
        offset = 983055
        lastIndex = <optimized out>
        nearestForwardSrcOffset = 68812800
        p = <optimized out>
        p0 = <optimized out>
        finalNode = <optimized out>
        doc = <optimized out>
        mainNode = <optimized out>
#1  0x346658e4 in ldomXPointer::toPoint (this=this@entry=0x7ee2ad00, extended=extended@entry=true) at /var/tmp/niluje/Build_KO/koreader/base/thirdparty/kpvcrlib/crengine/crengine/src/lvtinydom.cpp:9138
        rc = {left = 0, top = 0, right = 0, bottom = 0}
#2  0x345520be in getPosFromXPointer (L=0x2acfa1c8) at cre.cpp:901
--Type <RET> for more, q to quit, c to continue without paging--
        xpe = {<ldomXPointer> = {_data = 0x3f205ac8}, _indexes = {0, 0, 6, 0, 0, 0, 2, 1, 3, 715968512, -768, 2128784656, 286969, 10, -14, 718250936, 718250488, 727891884, 718253432, 718250440, -768, 2128784656, 338636, 3, 344544, 92, 92, 718250488, 127967, 2128784488, 127995, 2128784496, 133083, 92, 0, 10, -14, 0, 1073741824, 776993668, 150429, 0, 
            779948928, 2110540096, 2128784568, 71, 731963400, 56, 718250488, 56, 127967, 2128784576, 127995, 2128784584, 199221, 2040, 2128784592, -12, 2040, 730517048, 1, 2128784624, 242605, 730352160}, _level = 9}
        pt = {x = 10, y = -14}
        doc = <optimized out>
        xpointer_str = <optimized out>
        y = 0
        x = 0
        xp = {_data = 0x31b30190}
#3  0x00052710 in ?? ()
No symbol table info available.
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
NiLuJe commented 2 years ago

I can provide the core-dump and matching Kobo build if necessary.

NiLuJe commented 2 years ago

Similar bt from a live session, except we don't lose the LuaJIT magic bits ;p.

Program received signal SIGSEGV, Segmentation fault.
0x34589642 in ldomXPointer::getRect (this=this@entry=0x7e878820, rect=..., extended=<optimized out>, adjusted=adjusted@entry=false) at /var/tmp/niluje/Build_KO/koreader/base/thirdparty/kpvcrlib/crengine/crengine/src/lvtinydom.cpp:9634
9634    /var/tmp/niluje/Build_KO/koreader/base/thirdparty/kpvcrlib/crengine/crengine/src/lvtinydom.cpp: No such file or directory.
(gdb) bt full
#0  0x34589642 in ldomXPointer::getRect (this=this@entry=0x7e878820, rect=..., extended=<optimized out>, adjusted=adjusted@entry=false) at /var/tmp/niluje/Build_KO/koreader/base/thirdparty/kpvcrlib/crengine/crengine/src/lvtinydom.cpp:9634
        w = {61192, 15329, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 16, 0, 34148, 32391, 0, 0, 515, 0, 33504, 32391, 41821, 13398, 0, 0, 24, 73, 33520, 32391, 24576, 10959, 0, 0, 0, 0, 2, 0, 6288, 15330, 33544, 32391, 12048, 15330, 12312, 15330, 10, 0, 7248, 15330, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 
          0, 2, 0, 6, 0, 0, 0, 11, 0, 26608, 11258, 33640, 32391, 6329, 2, 32766, 0, 2048, 0, 33692, 32391, 33692, 32391, 41912, 10959, 33664, 32391, 0, 0, 33692, 32391, 41912, 10959, 33680, 32391, 0, 0, 12, 22, 0, 0, 12, 22, 33704, 32391, 9, 0, 0, 0, 12, 22, 33720, 32391, 41821, 13398, 0, 0, 64400, 72, 33736, 32391, 52377, 13398, 64400, 72, 12312, 15330, 
          24, 0, 24, 0, 41464, 10959, 62431, 1, 33768, 32391, 62459, 1, 33776, 32391, 2011, 2, 24, 0, 1, 0, 52712, 11150, 3, 0, 33808, 32391, 0, 0, 0, 0, 25955, 3, 4180, 10957, 10, 0, 0, 0, 41624, 10959, 28, 0, 1, 0, 52712, 11150, 41416, 10959...}
        flg = "\000`\317*\002\000\000\000\220\373H\000\220&\342;\270\200\207~\274g\317*\b\000\000\000\274g\317*\b\000\000\000\001\000\000\000\000\201\207~\001\000\000\000\000\000\000\000ȁ\207~\374\200\207~\260:\302*\002\000\000\000\000\000\000\000\002\000\000\000L\201\207~|\000\000\000w\000\000\000n\000\000\000[\000\000\000:", '\000' <repeats 19 times>, "\002\000\000\000\021\000\000\000\200\000\000\000\000`\317*\021\000\000\000T\020\315*(b\317*\314\032y4\000\000\000\000\000\020x4\274g\317*\200\000\000\000\000\000\000\000\220\201\207~\b\000\000\000\001\000\000\000\060\000I\000|\201\207~\260:\302*@1\342;\000\000\000\000\000\000\000\000"...
        str = {pchunk = 0x2a97a8, static EMPTY_STR_32 = 0x34791acc <empty_chunk_32>, static empty_str = {pchunk = 0x34791acc <empty_chunk_32>, static EMPTY_STR_32 = 0x34791acc <empty_chunk_32>, static empty_str = <same as static member of an already seen type>}}
        chx = <optimized out>
        font = 0x40100 <lj_cf_ffi_cast+64>
        hints = 0
        word = 0x42eac0
        word_is_rtl = <optimized out>
        lastWord = false
        w = <optimized out>
        frmline = 0x42ea88
        line_is_bidi = false
        l = <optimized out>
        fmt = {<lvdomElementFormatRec> = {_y = 1273, _height = 1005, _x = 0, _width = 1050, _inner_width = 1050, _inner_x = 0, _inner_y = 0, _baseline = 0, _usable_left_overflow = 15, _usable_right_overflow = 15, _top_overflow = 0, _bottom_overflow = 0, _lang_node_idx = 2241, _flags = 40, _extra0 = 0, _extra1 = 0, _extra2 = 0, _extra3 = 0, _extra4 = 0, 
            _extra5 = 0, _listprop_node_idx = 0}, _node = 0x490030, _modified = false, _dirty = false}
        inner_width = <optimized out>
        xp = {<ldomXPointer> = {_data = 0x3be218b0}, _indexes = {0, 0, 6, 0, 0, 0, 2, 1, 3, 4870664, 726639851, 2, 1, 852844520, 9411976, 2122809328, 726640423, 2, 0, 0, 2122809336, 2122811332, 0, 124, 119, 110, 91, 56, 0, 0, 0, 0, 0, 3, 16, 718233600, 3, 718082132, 718234152, 70, 878124053, 880283648, 718235580, 16, 761, 2122809496, 880283648, 1, 
            718233600, 2122809476, 0, 852839984, 0, 0, 1441804, 0, 1441804, 2122809480, 878093149, 0, 1441804, 2, 8, 2}, _level = 9}
        bestBidiRect = {left = 0, top = 0, right = 0, bottom = 0}
        rc = {left = 6, top = 8993, right = 1056, bottom = 9998}
        srcLen = 1005
        lastOffset = <optimized out>
        nearestForwardSrcIndex = <optimized out>
        hasBestBidiRect = 26
        node = 0x0
        srcIndex = <optimized out>
        lastLen = <optimized out>
        txtform = {_ptr = 0x796748}
        offset = 983055
        lastIndex = <optimized out>
        nearestForwardSrcOffset = 68812800
        p = <optimized out>
        p0 = <optimized out>
        finalNode = <optimized out>
        doc = <optimized out>
        mainNode = <optimized out>
#1  0x345898e4 in ldomXPointer::toPoint (this=this@entry=0x7e878820, extended=extended@entry=true) at /var/tmp/niluje/Build_KO/koreader/base/thirdparty/kpvcrlib/crengine/crengine/src/lvtinydom.cpp:9138
        rc = {left = 0, top = 0, right = 0, bottom = 0}
#2  0x344760be in getPosFromXPointer (L=0x2acfa1c8) at cre.cpp:901
        xpe = {<ldomXPointer> = {_data = 0x3be23140}, _indexes = {0, 0, 6, 0, 0, 0, 2, 1, 3, 3, 9, 0, 8192, 0, 1092776962, 153, 2122811244, 153, 718236704, 76, 76, 718250488, 127967, 2122811248, 127995, 92, 92, 718250488, 127967, 2122811272, 127995, 2122811280, 133083, 92, 0, 0, 1092776962, 0, 1076887552, 729766732, 150429, 0, 739584432, 833528482, 
            2122811352, 71, 731926536, 56, 718250488, 56, 127967, 2122811360, 127995, 2122811368, 199221, 2040, 2122811376, -12, 2040, 734632216, 1, 2122811408, 242605, 729824720}, _level = 9}
        pt = {x = 718071856, y = 718090344}
        doc = <optimized out>
        xpointer_str = <optimized out>
--Type <RET> for more, q to quit, c to continue without paging--c
        y = 0
        x = 0
        xp = {_data = 0x3be23128}
#3  0x00052710 in lj_BC_FUNCC () at buildvm_arm.dasc:928
No locals.
#4  0x0004b66a in lua_pcall (L=L@entry=0x2acfa1c8, nargs=nargs@entry=0, nresults=-1, errfunc=errfunc@entry=2) at lj_api.c:1145
        g = 0x2acfa1f8
        oldh = 0 '\000'
        ef = <optimized out>
        status = <optimized out>
#5  0x00013936 in docall (L=L@entry=0x2acfa1c8, narg=narg@entry=0, clear=clear@entry=0) at luajit.c:122
        status = <optimized out>
        base = 2
#6  0x00013f4a in handle_script (L=L@entry=0x2acfa1c8, argx=argx@entry=0x7e878b28) at luajit.c:292
        narg = 0
        status = <optimized out>
        fname = <optimized out>
#7  0x00014486 in pmain (L=0x2acfa1c8) at luajit.c:550
        s = 0x6b1bc <smain>
        argv = 0x7e878b24
        argn = 1
        flags = 0
#8  0x00052710 in lj_BC_FUNCC () at buildvm_arm.dasc:928
No locals.
#9  0x0004b74e in lua_cpcall (L=L@entry=0x2acfa1c8, func=<optimized out>, ud=ud@entry=0x0) at lj_api.c:1173
        g = 0x2acfa1f8
        oldh = 0 '\000'
        status = <optimized out>
#10 0x00014520 in main (argc=2, argv=0x7e878b24) at luajit.c:581
        status = <optimized out>
        L = 0x2acfa1c8
poire-z commented 2 years ago

Thanks. I couldn't reproduce it by following your steps, changing font size to get xrkvc near the top... But I can if I tap on the footnote link (or follow it with a swipe) on that second page. Will investigate. (Same backtrace as you - so, no need for more info :)

Frenzie commented 2 years ago

Glad you figured it out. :-)

poire-z commented 2 years ago

Good news is that it seems caused by something recent :) and the footnote link having some left margin (.apnb { margin: 0 0 0 0.2em }) and my added support for that in https://github.com/koreader/crengine/pull/477, and my: https://github.com/koreader/crengine/blob/de482f93541f50509ba1d76fd3145ccdaf37e60a/crengine/src/lvtinydom.cpp#L9567 being proved wrong :|

poire-z commented 2 years ago

Couldn't reproduce a crash in RTL text... Anyway, should be solved by skipping such "words" early:

--- a/crengine/src/lvtinydom.cpp
+++ b/crengine/src/lvtinydom.cpp
@@ -9336,6 +9336,11 @@ bool ldomXPointer::getRect(lvRect & rect, bool extended, bool adjusted) const
             bool line_is_bidi = frmline->flags & LTEXT_LINE_IS_BIDI;
             for ( int w=0; w<(int)frmline->word_count; w++ ) {
                 const formatted_word_t * word = &frmline->words[w];
+                if (word->flags & LTEXT_WORD_IS_PAD ) {
+                    // Skip these as they are virtual and don't map to real nodes
+                    // text indices: they won't be part of any rect
+                    continue;
+                }
                 bool word_is_rtl = word->flags & LTEXT_WORD_DIRECTION_IS_RTL;
                 bool lastWord = (l == txtform->GetLineCount() - 1
                                  && w == frmline->word_count - 1);