Skip to content

<vector>: iterator debugging misses a check before dereferencing #3281

@rogerorr

Description

@rogerorr

Description
When iterator debugging is enabled and a vector iterator is invalidated, for example by a call to erase at or before the referenced element, an attempt to dereference the iterator causes an access violation.

Command-line test case

C:\Temp>type repro.cpp
#include <vector>

int main() {
  std::vector<int> v({0,1,2,3});
  auto iter = v.begin();
  v.erase(v.begin()); // invalidate iter
  return *iter; // access violation, rather than an assertion
}
c:\temp>cl /EHsc /Zi /MDd repro.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.34.31935 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

repro.cpp
Microsoft (R) Incremental Linker Version 14.34.31935.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:repro.exe
/debug
repro.obj

c:\temp>repro

c:\temp>echo %ERRORLEVEL%
-1073741819

c:\temp>

The error code is that of STATUS_ACCESS_VIOLATION 0xC0000005 ("The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.").

Expected behavior
I was hoping to have an assert failure from the iterator dereference in <vector>.
What happens is an access violation.
The affected code is:

45     _NODISCARD _CONSTEXPR20 reference operator*() const noexcept {
46 #if _ITERATOR_DEBUG_LEVEL != 0
47         const auto _Mycont = static_cast<const _Myvec*>(this->_Getcont());
48         _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator");
49         _STL_VERIFY(
50             _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator");
51 #endif // _ITERATOR_DEBUG_LEVEL != 0
52 
53        return *_Ptr;
54     }

The AV occurs at line 49/50 as _Mycont is null; this is becasue the call to erase that invalidated the iterator changed the fields in the base class _Iterator_base12 to reflect this, such that _Getcont() now returns null by design:
In <vector>:

2216             } else { // orphan the iterator
2217                _Temp->_Myproxy = nullptr;

STL version
Microsoft Visual Studio Community 2022 (64-bit) - Current
Version 17.4.2

Possible Proposed Resolution
Add a new line between lines 48 and 49:

        _STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator");

The check takes place after the check on _Ptr, which detects ''uninitialised'' iterators, and before the problematic dereference of _Mycont.

A similar additional line could be added to other methods which perform similar checking, such as operator->.

I'm raising a P/R ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSomething can be improvedfixedSomething works now, yay!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions