Created attachment 62126 [details] error message and backtrace At the stage described in bug 47520 comment 3 <https://bugs.freedesktop.org/show_bug.cgi?id=47520#c3> step 7, the program issues message "attempt to dereference a past-the-end iterator" and aborts. The attached typescript shows the failure and gdb backtrace. I have built from master commit d015384, pulled 2012-05-20, configured as ... --disable-mozilla --enable-symbols --enable-dbgutil --enable-crashdump --disable-build-mozilla --without-system-postgresql --enable-debug and running on ubuntu-natty (11.04). Working backward in the code and gdb, I observe ... (*) The dereference happens in OKeySet::refreshRow(), KeySet.cxx line 1338. At this point, m_aKeyIter equals m_aKeyMap.end(). The error message is true. (*) m_aKeyIter became equal to m_aKeyMap.end() when OKeySet::refreshRow(), KeySet.cxx line 1348 increamented the iterator before the recursive call to OKeySet::refreshRow(). After line 1349 erases the previously addressed element of m_aKeyMap, m_aKeyMap.size() is 2. A couple of simple-minded hacks to the code ( early return from recursive call to OKeySet::refreshRow(); decrementing instead of incrementing the pointer before the recursive call ) merely defer the crash to later in execution. Guidance welcome.
Created attachment 62166 [details] test patch I didn't try to reproduce on pc Debian x86-64 (master sources updated today). But could you try the patch attached ? functionnally / technically: if you're at the last row (hope I well interpreted the code), you - don't need to / can't - refresh the next row since there's no next row
I have tried a couple of hacks which only deferred the failure to later points in execution. (*) The first of these hacks was equivalent to the patch you propose: an early return from OKeySet::refreshRow if m_aKeyIter equals m_aKeyMap.end(). This makes OKeySet::getBookmark() fail with message "getBookmark is possible only when we stand on a valid row!". Note that the test isAfterLast() early in OKeySet::refreshRow() is not a sufficient guard against past-the-end iterator because OKeySet::isAfterLast() looks first at m_bRowCountFinal. So, beyond the present problem, I wonder whether there is some reason to expect that OKeySet::refreshRow() is never called with false m_bCountFinal and m_aKeyIter equal m_aKeyMap.end(); I think this combination would make the routine fail every time. (*) The second was to replace the increment of m_aKeyIter with a decrement before KeySet::refreshRow() does the recursive call. (Yes, the table has two rows. And I *think* the first element of m_aKeyMap is a dummy anyway, existing just to allow a before-the-first test like the after-the-last test which STL provides. So, I guessed that at worst this would result in an return from the recursive call because isBeforeFirst().) I think this led to a failure within OSL_ENSURE within OKeySet::getInt(), KeySet.cxx line 1441. (Just "I think" because I made a mess of my notes and silly me was not collecting a typescript.) As the program seems to have fetched all two rows of the table, I suspect that m_aRowCountFinal should be true--maybe, perhaps. But, all I know about that variable is its name and the fact that it seems to be used a lot. And the result of my first hack suggests that that might not be sufficient to fix the problem anyway. From my comment on bug 47520, it looks like LO as of 2012-04-01 did not crash opening this table. As I am running a 32-bit system, I cannot use bibisect. Besides, bibsect is only updated to late April, IIRC.
You're right Terrence, I reproduced the initial bug and as you said, reproduced the fail with the patch I had attached :-( A Base dev guru seems to be needed here (hum, let's see...Lionel ? :-))
Another experimental hack: I added guard ( m_aKeyIter != m_aKeyMap.end() ) to the originally failing ... m_aKeyIter->second.second.second.is() This was followed by a past-the-end iterator in dbaccess::OKeySet::doTryRefetch_throw(), KeySet.cxx line 1295, which reads ... OUpdatedParameter::iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first); The backtrace shows ... #5 0x062e413e in dbaccess::OKeySet::doTryRefetch_throw (this=0x9052388) at /home/terry/lo_hacking/git/libo/dbaccess/source/core/api/KeySet.cxx:1295 #6 0x062e4b77 in dbaccess::OKeySet::refreshRow (this=0x9052388) at /home/terry/lo_hacking/git/libo/dbaccess/source/core/api/KeySet.cxx:1344 #7 0x062e4c12 in dbaccess::OKeySet::refreshRow (this=0x9052388) at /home/terry/lo_hacking/git/libo/dbaccess/source/core/api/KeySet.cxx:1351 #8 0x062e2e0b in dbaccess::OKeySet::next (this=0x9052388) at /home/terry/lo_hacking/git/libo/dbaccess/source/core/api/KeySet.cxx:1115 #9 0x063641d5 in dbaccess::ORowSetCache::fillMatrix (this=0x9052018, _nNewStartPos=@0xbfffcb64, _nNewEndPos=@0xbfffcbb4) at /home/terry/lo_hacking/git/libo/dbaccess/source/core/api/RowSetCache.cxx:827 The symptoms are different from bug 48345, so I am not marking this a duplicate; but the two bugs do seem to have code in common. I shall add a comment to that effect in bug 48345.
My guess is that maybe some previous code moved the current record without updating m_aKeyIter. Will try to take a look. I suspect it is related to the fix of bug 48345
What is "the current row" other than whatever m_aKeyIter points to? If it could mean an element of m_aKeyMap, perchance ... well, the previously current element fell victim to `m_aKeyMap.erase(aTemp);` at KeySet.xxx line 1349.
Fixed in my development tree. Will push later today.
Lionel Elie Mamane committed a patch related to this issue. It has been pushed to "master": http://cgit.freedesktop.org/libreoffice/core/commit/?id=76a74b72db45a5aa3f064034e0fa05440aefb52b fdo#50372: crash when refresh of last already-known row unexpectedly fails
Lionel Elie Mamane committed a patch related to this issue. It has been pushed to "libreoffice-3-5": http://cgit.freedesktop.org/libreoffice/core/commit/?id=38786a76cf3dbc421635d40354e8c9ece409c6c5&g=libreoffice-3-5 fdo#50372: crash when refresh of last already-known row unexpectedly fails It will be available in LibreOffice 3.5.5.
The past-the-end iterator seems to be fixed. Thank you, Lionel, for this. Of course, fdo#50575 remains.