[Scummvm-tracker] [ScummVM :: Bugs] #11494: Possible usage of invalid iterators

ScummVM :: Bugs trac at scummvm.org
Wed Jun 3 13:20:43 UTC 2020


#11494: Possible usage of invalid iterators
-----------------------------------------+-----------------------
Reporter:  Tkachov                       |      Owner:  (none)
    Type:  defect                        |     Status:  new
Priority:  low                           |  Component:  --Unset--
Keywords:  iterators, invalidate, erase  |       Game:
-----------------------------------------+-----------------------
 I've stumbled onto C++ iterators-related comment (in Russian:
 https://habr.com/ru/post/492410/#comment_21566838): someone cached
 `collection.end()` and then used `i = collection.erase(i)`, which
 invalidates old iterators.

 So I've decided to look through ScummVM code and I've found some places I
 think might use invalid iterators. I've used GitHub search and briefly
 read the files, so I might've skipped something or made a false positive
 mistake. Also, I'm not sure if ScummVM iterators invalidate after
 `erase()` or not.

 Anyways, here are these places:

 [https://github.com/scummvm/scummvm/blob/30c00656e1d6e6e8420c662755527ac3b08ee8ff/backends/timer/default
 /default-timer.cpp#L187L189]

 {{{
         for (TimerSlotMap::iterator i = _callbacks.begin(), end =
 _callbacks.end(); i != end; ++i) {
                 if (i->_value == callback)
                         _callbacks.erase(i);
 }}}

 1. `_callbacks.end()` is cached, but `erase()` is used.
 2. `erase()` returns new valid iterator, but this code continues to use
 the old one.

 ----

 [https://github.com/scummvm/scummvm/blob/46ba0500cebf4ed6334d43b6b48b2079f06d05d0/engines/ultima/ultima8/gumps/gump.cpp#L63L67]

 {{{
         Std::list<Gump *>::iterator end = _children.end();

         while (it != end) {
                 Gump *g = *it;
                 it = _children.erase(it);
 }}}

 `erase()` probably invalidates that cached `end`. Comment up there says
 "Delete all children", so I don't see why `erase()` is even needed. One
 could iterate through all the children, deleting each of them and then use
 `clear()`. Or, maybe, do something like this:
 {{{
 while (!ch.empty()) {
         delete *ch.begin();
         ch.erase(ch.begin());
 }
 }}}

 ----

 [https://github.com/scummvm/scummvm/blob/1a097b1d971e6e3cf3c10f6eb7c7a30def2d2f7c/engines/cruise/gfxModule.cpp#L252L265]
 and the same code at
 [https://github.com/scummvm/scummvm/blob/1a097b1d971e6e3cf3c10f6eb7c7a30def2d2f7c/engines/tony/gfxcore.cpp#L398L412]

 {{{
         for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end();
 ++rOuter) {
                 rInner = rOuter;
                 while (++rInner != _dirtyRects.end()) {
                                 ...
                                 // remove the inner rect from the list
                                 _dirtyRects.erase(rInner);

                                 // move back to beginning of list
                                 rInner = rOuter;
 }}}

 I see why this probably works: `erase()` only invalidates iterators
 pointing to elements further than the erased one, so earlier iterators are
 fine. If that's not so, `rOuter` should be as invalid as `rInner`, and
 code probably should be rewritten to use integer indexes instead.

 ----

 [https://github.com/scummvm/scummvm/blob/6ed8dea8297480d4c42ed0d38a23734df48067e6/engines/zvision/graphics/render_manager.cpp#L743]

 {{{
 _subsList.erase(it);
 }}}

 The cycle goes on without `break` or `return` there, so `erase()` return
 value should be used to update `it` and `it++` should not be called.

 ----

 [https://github.com/scummvm/scummvm/blob/e3abab45ab27349a6296a5c3c447d331f3e5167b/engines/gob/inter.h#L61]

 {{{
 #define CLEAROPCODEGOB(i)  _opcodesGob.erase(i)
 }}}

 I couldn't find usages of `CLEAROPCODEGOB`, so I don't know if that is
 even related to iterators, but if it is, its return value should be used
 and `end()` around there should not be cached.
-- 
Ticket URL: <https://bugs.scummvm.org/ticket/11494>
ScummVM :: Bugs <https://bugs.scummvm.org>
ScummVM


More information about the Scummvm-tracker mailing list