From a403d0e675f8c07ded3a83b58771341a66aa36ca Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 12 Jul 2017 10:18:09 -0400 Subject: [PATCH] Fix past-the-end dereference in values_and_holders The value and holder iterator code had a past-the-end iterator dereference. While of course invalid, the dereference didn't actually cause any problems (which is why it wasn't caught before) because the dereferenced value is never actually used and `vector` implementations appear to allow dereferencing the past-the-end iterator. Under a MSVC debug build, however, it fails a debug assertion and aborts. This amends the iterator to just store and use a pointer to the vector (rather than adding a second past-the-end iterator member), checking the type index against the type vector size. --- include/pybind11/cast.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index c7b8edc6..27d5622c 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -311,14 +311,13 @@ public: struct iterator { private: instance *inst; - using vec_iter = std::vector::const_iterator; - vec_iter typeit; + const type_vec *types; value_and_holder curr; friend struct values_and_holders; - iterator(instance *inst, const type_vec &tinfo) - : inst{inst}, typeit{tinfo.begin()}, + iterator(instance *inst, const type_vec *tinfo) + : inst{inst}, types{tinfo}, curr(inst /* instance */, - tinfo.size() > 0 ? *typeit : nullptr /* type info */, + types->empty() ? nullptr : (*types)[0] /* type info */, 0, /* vpos: (non-simple types only): the first vptr comes first */ 0 /* index */) {} @@ -328,18 +327,17 @@ public: bool operator==(const iterator &other) { return curr.index == other.curr.index; } bool operator!=(const iterator &other) { return curr.index != other.curr.index; } iterator &operator++() { - if (!inst->simple_layout) { - curr.vh += 1 + (*typeit)->holder_size_in_ptrs; - curr.type = *(++typeit); - } + if (!inst->simple_layout) + curr.vh += 1 + (*types)[curr.index]->holder_size_in_ptrs; ++curr.index; + curr.type = curr.index < types->size() ? (*types)[curr.index] : nullptr; return *this; } value_and_holder &operator*() { return curr; } value_and_holder *operator->() { return &curr; } }; - iterator begin() { return iterator(inst, tinfo); } + iterator begin() { return iterator(inst, &tinfo); } iterator end() { return iterator(tinfo.size()); } iterator find(const type_info *find_type) {