| Bug #95062 | Invalid assertion in Cmp_splocal_locations::operator() | ||
|---|---|---|---|
| Submitted: | 19 Apr 2019 8:27 | Modified: | 7 Jun 2019 17:36 |
| Reporter: | Alexey Kopytov | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Stored Routines | Severity: | S6 (Debug Builds) |
| Version: | 5.7, 8.0 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[23 Apr 2019 6:33]
Alexey Kopytov
If it helps verification, the assertion I'm referring to has been introduced with the following commit: 4c715b798e15b7b92dcec473ef918e89176bd00e Author: Tor Didriksen <tor.didriksen@oracle.com> AuthorDate: Tue Nov 26 09:49:06 2013 +0100 Commit: Tor Didriksen <tor.didriksen@oracle.com> CommitDate: Tue Nov 26 09:49:06 2013 +0100 Bug#17781461 GET RID OF DYNAMIC_ARRAY IN THE SP CODE Patch number 2: remove Dynamic_array from sp_rcontext and sp_instr as well.
[9 May 2019 14:03]
MySQL Verification Team
Hi Kaamos, my dear friend, I have analysed carefully the problem with the above assertion and I agree with you 100 %. Verified as reported.
[7 Jun 2019 17:36]
Paul DuBois
Posted by developer: Fixed in 5.7.27, 8.0.17. An overly strict assertion could be raised during sorting of stored program local objects.
[10 Jun 2019 12:39]
MySQL Verification Team
Thank you, Paul and thanks a lot, Kaamos .....

Description: Cmp_splocal_locations::operator() in sp_instr.cc has a debug assertion which I think is too narrow: class Cmp_splocal_locations : public std::binary_function<const Item_splocal *, const Item_splocal *, bool> { public: bool operator()(const Item_splocal *a, const Item_splocal *b) { DBUG_ASSERT(a->pos_in_query != b->pos_in_query); return a->pos_in_query < b->pos_in_query; } }; The function is used to sort an array of pointers to Item_splocal objects in subst_spvars() using std::sort(). The comparison is performed using the pos_in_query member variable of Item_splocal. Apparently, the assertion is intended to ensure there are never duplicate pos_in_query values for different elements of the array. However, it doesn't take into account that std::sort() may sometimes compare an element to itself, in which case a->pos_in_query would be equal to b->pos_in_query, since a == b. This behavior is implementation-defined, but I have been unable to find anything that would prevent std::sort() from comparing elements to themselves. Background: I'm looking into a couple of MTR test failures for debug builds. The reason is the mentioned assertion failing because std::sort() calls Cmp_splocal_local::operator() with a == b, even though all array elements have different pos_in_query values. The failures occur on some platforms (macOS 10.14, CentOS 6), but not on the others (tested on CentOS 7 and Ubuntu 18.04). Removing the assertion or replacing std::sort() with std::stable_sort(), for example, makes the problem disappear, but I think the correct fix is relaxing the assertion. How to repeat: - Look at DBUG_ASSERT() in Cmp_splocal_location::operator() - note that the assertion would fail if passed two equal pointers (i.e. a == b) - try to find a single reason why a std::sort() implementation cannot compare elements to themselves for code optimization purposes or whatnot. Suggested fix: Relax the assertion from: DBUG_ASSERT(a->pos_in_query != b->pos_in_query); to: DBUG_ASSERT(a == b || a->pos_in_query != b->pos_in_query);