r263433 moved some checking from std::__rotate to its caller, std::rotate. It's no longer safe to combine code compiled before and after that change: tmp$ cat rot1.cc #include <algorithm> namespace std { // explicit instantiation definition to simulate the linker choosing the // definition from this file. template int* __rotate(int*, int*, int*, random_access_iterator_tag); } tmp$ cat rot2.cc #include <algorithm> namespace std { // explicit instantiation definition to simulate the linker choosing a // definition from another file. extern template int* __rotate(int*, int*, int*, random_access_iterator_tag); } int main() { int i = 0; std::rotate(&i, &i, &i+1); } tmp$ /home/jwakely/gcc/9.1.0/bin/g++ -c rot1.cc tmp$ /home/jwakely/gcc/8.3.0/bin/g++ -c rot2.cc tmp$ /home/jwakely/gcc/9.1.0/bin/g++ rot1.o rot2.o tmp$ ./a.out Floating point exception (core dumped)
The problem case happens when std::rotate is compiled with the old headers and std::__rotate is compiled with the new code, and so neither function checks for an empty range. Reverting the patch is easy, but that doesn't help code already compiled with GCC 9.1, which has non-checking instantiations of std::__rotate.
Author: redi Date: Wed Jun 19 22:57:02 2019 New Revision: 272489 URL: https://gcc.gnu.org/viewcvs?rev=272489&root=gcc&view=rev Log: PR libstdc++/90920 restore previous checks for empty ranges The change in r263433 broke the contract of the __rotate functions, by no longer accepting empty ranges. That means that callers which inlined the old version of std::rotate (without checks) that end up linking to a new definition of std::__rotate (also without checks) could perform a divide by zero and crash. This restores the old contract of the __rotate overloads. PR libstdc++/90920 partially revert r263433 * include/bits/stl_algo.h (__rotate): Restore checks for empty ranges. (rotate): Remove checks. * testsuite/25_algorithms/rotate/90920.cc: New test. Added: trunk/libstdc++-v3/testsuite/25_algorithms/rotate/90920.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/bits/stl_algo.h
Fixed on trunk. I think I rather prefer the one-off incompatibility in 9.1. Unless you can think of a solution not breaking compatibility with 9.1 of course.
I did experiment with putting the range checks in *both* places, the std::rotate function and the std::__rotate helpers it calls. But there's still no guarantee you won't get a "bad" combination of definitions from objects built with e.g. 9.1 and 8.3 If we change the mangled names to make the "new" functions different that doesn't help, because the "old" functions will still be present in already-built objects. Basically nothing we can do will fix the code in already compiled objects. The only guaranteed way to avoid the problem is to recompile anything built with 9.1, and if you have to do that anyway, then the fix I put on trunk works fine. So I think I'll just backport the same fix, and 9.1 will be a blip.
On June 20, 2019 6:42:10 PM GMT+02:00, "redi at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org> wrote: >https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90920 > >--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> --- >I did experiment with putting the range checks in *both* places, the >std::rotate function and the std::__rotate helpers it calls. But >there's still >no guarantee you won't get a "bad" combination of definitions from >objects >built with e.g. 9.1 and 8.3 > >If we change the mangled names to make the "new" functions different >that >doesn't help, because the "old" functions will still be present in >already-built objects. > >Basically nothing we can do will fix the code in already compiled >objects. The >only guaranteed way to avoid the problem is to recompile anything built >with >9.1, and if you have to do that anyway, then the fix I put on trunk >works fine. > >So I think I'll just backport the same fix, and 9.1 will be a blip. Sounds good. Please document this on changes. Html in some prominent place (caveats section).
Author: redi Date: Fri Jun 21 17:37:07 2019 New Revision: 272558 URL: https://gcc.gnu.org/viewcvs?rev=272558&root=gcc&view=rev Log: PR libstdc++/90920 restore previous checks for empty ranges The change in r263433 broke the contract of the __rotate functions, by no longer accepting empty ranges. That means that callers which inlined the old version of std::rotate (without checks) that end up linking to a new definition of std::__rotate (also without checks) could perform a divide by zero and crash. This restores the old contract of the __rotate overloads. Backport from mainline 2019-06-19 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/90920 partially revert r263433 * include/bits/stl_algo.h (__rotate): Restore checks for empty ranges. (rotate): Remove checks. * testsuite/25_algorithms/rotate/90920.cc: New test. Added: branches/gcc-9-branch/libstdc++-v3/testsuite/25_algorithms/rotate/90920.cc Modified: branches/gcc-9-branch/libstdc++-v3/ChangeLog branches/gcc-9-branch/libstdc++-v3/include/bits/stl_algo.h
Fixed for 9.2
.