Skip to content

Commit 7187c61

Browse files
author
Jonathan Brandmeyer
committed
Throw an IndexError when given an extended slice;
Clip bounds of slices in a mannar consistant with builtin containers; Prevent undefined behavior within the STL when given certain kinds of empty slices. [SVN r22507]
1 parent b3f0d7c commit 7187c61

File tree

2 files changed

+57
-13
lines changed

2 files changed

+57
-13
lines changed

include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# include <boost/detail/binary_search.hpp>
1414
# include <vector>
1515
# include <map>
16+
#include <iostream>
1617

1718
namespace boost { namespace python { namespace detail {
1819

@@ -507,9 +508,9 @@ namespace boost { namespace python { namespace detail {
507508
static object
508509
base_get_item_(back_reference<Container&> const& container, PyObject* i)
509510
{
510-
// Proxy
511+
// Proxy
511512
Index idx = DerivedPolicies::convert_index(container.get(), i);
512-
513+
513514
if (PyObject* shared =
514515
ContainerElement::get_links().find(container.get(), idx))
515516
{
@@ -570,15 +571,42 @@ namespace boost { namespace python { namespace detail {
570571
base_get_slice_data(
571572
Container& container, PySliceObject* slice, Index& from, Index& to)
572573
{
573-
if (Py_None == slice->start)
574-
from = DerivedPolicies::get_min_index(container);
575-
else
576-
from = DerivedPolicies::convert_index(container, slice->start);
574+
if (Py_None != slice->step) {
575+
PyErr_SetString( PyExc_IndexError, "slice step size not supported.");
576+
throw_error_already_set();
577+
}
577578

578-
if (Py_None == slice->stop)
579+
Index min_index = DerivedPolicies::get_min_index(container);
580+
Index max_index = DerivedPolicies::get_max_index(container);
581+
582+
583+
if (Py_None == slice->start) {
584+
from = min_index;
585+
}
586+
else {
587+
from = extract<long>( slice->start);
588+
if (from < 0) // Negative slice index
589+
from += max_index;
590+
if (from < 0) // Clip lower bounds to zero
591+
from = 0;
592+
if (from > max_index) // Clip upper bounds to max_index.
593+
from = max_index;
594+
595+
}
596+
597+
if (Py_None == slice->stop) {
579598
to = DerivedPolicies::get_max_index(container);
580-
else
581-
to = DerivedPolicies::convert_index(container, slice->stop);
599+
}
600+
else {
601+
to = extract<long>( slice->stop);
602+
if (to < 0)
603+
to += max_index;
604+
if (to < 0)
605+
to = 0;
606+
if (to > max_index)
607+
to = max_index;
608+
}
609+
582610
}
583611

584612
static void

include/boost/python/suite/indexing/vector_indexing_suite.hpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ namespace boost { namespace python {
8181
static object
8282
get_slice(Container& container, index_type from, index_type to)
8383
{
84+
if (from > to)
85+
return object(Container());
8486
return object(Container(container.begin()+from, container.begin()+to));
8587
}
8688

@@ -94,17 +96,27 @@ namespace boost { namespace python {
9496
set_slice(Container& container, index_type from,
9597
index_type to, data_type const& v)
9698
{
97-
container.erase(container.begin()+from, container.begin()+to);
98-
container.insert(container.begin()+from, v);
99+
if (from > to) {
100+
return;
101+
}
102+
else {
103+
container.erase(container.begin()+from, container.begin()+to);
104+
container.insert(container.begin()+from, v);
105+
}
99106
}
100107

101108
template <class Iter>
102109
static void
103110
set_slice(Container& container, index_type from,
104111
index_type to, Iter first, Iter last)
105112
{
106-
container.erase(container.begin()+from, container.begin()+to);
107-
container.insert(container.begin()+from, first, last);
113+
if (from > to) {
114+
container.insert(container.begin()+from, first, last);
115+
}
116+
else {
117+
container.erase(container.begin()+from, container.begin()+to);
118+
container.insert(container.begin()+from, first, last);
119+
}
108120
}
109121

110122
static void
@@ -116,6 +128,10 @@ namespace boost { namespace python {
116128
static void
117129
delete_slice(Container& container, index_type from, index_type to)
118130
{
131+
if (from > to) {
132+
// A null-op.
133+
return;
134+
}
119135
container.erase(container.begin()+from, container.begin()+to);
120136
}
121137

0 commit comments

Comments
 (0)