boostorg / boostorg/python

boost::python::objects::iterator_range::next::operator() might return reference to temporary object

Aberta
#61 1 comentário 0 reações 0 responsáveis Ver no GitHub
Linguagem predominante
C++
Estrelas
537
Forks
223
Merge médio
11h 22min
PRs com merge (30d)
2

Descrição

`iterator_range` in boost/python/object/iterator.hpp defines an inner class called `next` which defines `operator()` (see https://github.com/boostorg/python/blob/develop/include/boost/python/object/iterator.hpp#L44). Here is the implementation:

```
result_type
operator()(iterator_range& self)
{
if (self.m_start == self.m_finish)
stop_iteration_error();
return *self.m_start++;
}
```

The last line is a potential problem as a temporary object (the return value of `self.m_start++`) is dereferenced. If `result_type` is a reference (meaning `operator()` returns a reference) and the dereferenced temporary object returns a reference to something within the temporary object, you get a dangling reference.

Here is how `result_type` is determined:

```
typedef boost::detail::iterator_traits traits_t;

typedef typename mpl::if_<
is_reference<
typename traits_t::reference
>
, typename traits_t::reference
, typename traits_t::value_type
>::type result_type;
```

In general this code looks good. However it implies that if a reference is returned, the reference does not refer to something in the iterator (as with the current implementation the iterator is a temporary object).

Here is an attempt to fix `operator()`:

```
result_type
operator()(iterator_range& self)
{
if (self.m_start == self.m_finish)
stop_iteration_error();
self.m_current = self.m_start++;
return *self.m_current;
}
```

Here an additional member variable called `m_current` is used to turn the temporary object returned by `self.m_start++` into something which lives longer. I tested this fix, and it seems to work. However I didn't test it thoroughly (for example, I don't know when and where Boost.Python creates copies of `iterator_range`; if you have a reference to something within a member variable, the member variable better doesn't change its location in memory :).

A valid question is of course whether this is a Boost.Python issue. First, I'm opening this ticket to document this issue (for others and also for myself ;). Secondly, I would be already happy if Boost.Python somehow supports me detecting this issue at compile-time (I'm fine if I get a compiler error and know I need to work around something). Thirdly, I'm working with a third-party library where iterators return references to something within iterators - it's easier for me to fix Boost.Python than all the iterators in the third-party library.

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Direção de pesquisa

Comece em include/boost/python/object/iterator.hpp, em iterator_range::next::operator(), e inspecione como result_type, o pós-incremento e as cópias do iterador afetam o tempo de vida das referências. Reproduza o caso com um iterador cujo pós-incremento retorna um temporário e determine então se o comportamento suportado deve impedir referências pendentes ou expor uma limitação em tempo de compilação; considera-se concluído quando houver uma resolução documentada e cobertura de regressão.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
cpp
Domínio
api
Tipo de issue
Bug
Dificuldade
5/5
Tempo estimado
Mais de uma semana
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
35/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.