Skip to content

Commit d6f4eaa

Browse files
author
William Nolan
committed
* Changes to fix Subsetter's use of 'int' for indexing
1 parent 47db24c commit d6f4eaa

File tree

2 files changed

+42
-29
lines changed

2 files changed

+42
-29
lines changed

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2018-11-09 William Nolan <[email protected]>
2+
3+
* inst/include/Rcpp/vector/Subsetter.h: Fixed to use R_xlen_t instead of int for indexing
4+
and added warning when indexing by IntegerVector (only for large enough vectors)
5+
16
2018-11-05 Dirk Eddelbuettel <[email protected]>
27

38
* DESCRIPTION (Date, Version): Version 1.0, and happy 10th birthday!

inst/include/Rcpp/vector/Subsetter.h

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#ifndef Rcpp_vector_Subsetter_h_
2323
#define Rcpp_vector_Subsetter_h_
2424

25+
#include <limits>
26+
2527
namespace Rcpp {
2628

2729
template <
@@ -51,14 +53,14 @@ class SubsetProxy {
5153
// Enable e.g. x[y] = z
5254
template <int OtherRTYPE, template <class> class OtherStoragePolicy>
5355
SubsetProxy& operator=(const Vector<OtherRTYPE, OtherStoragePolicy>& other) {
54-
int n = other.size();
56+
R_xlen_t n = other.size();
5557

5658
if (n == 1) {
57-
for (int i=0; i < indices_n; ++i) {
59+
for (R_xlen_t i=0; i < indices_n; ++i) {
5860
lhs[ indices[i] ] = other[0];
5961
}
6062
} else if (n == indices_n) {
61-
for (int i=0; i < n; ++i) {
63+
for (R_xlen_t i=0; i < n; ++i) {
6264
lhs[ indices[i] ] = other[i];
6365
}
6466
} else {
@@ -70,28 +72,28 @@ class SubsetProxy {
7072
// Enable e.g. x[y] = 1;
7173
// TODO: std::enable_if<primitive> with C++11
7274
SubsetProxy& operator=(double other) {
73-
for (int i=0; i < indices_n; ++i) {
75+
for (R_xlen_t i=0; i < indices_n; ++i) {
7476
lhs[ indices[i] ] = other;
7577
}
7678
return *this;
7779
}
7880

7981
SubsetProxy& operator=(int other) {
80-
for (int i=0; i < indices_n; ++i) {
82+
for (R_xlen_t i=0; i < indices_n; ++i) {
8183
lhs[ indices[i] ] = other;
8284
}
8385
return *this;
8486
}
8587

8688
SubsetProxy& operator=(const char* other) {
87-
for (int i=0; i < indices_n; ++i) {
89+
for (R_xlen_t i=0; i < indices_n; ++i) {
8890
lhs[ indices[i] ] = other;
8991
}
9092
return *this;
9193
}
9294

9395
SubsetProxy& operator=(bool other) {
94-
for (int i=0; i < indices_n; ++i) {
96+
for (R_xlen_t i=0; i < indices_n; ++i) {
9597
lhs[ indices[i] ] = other;
9698
}
9799
return *this;
@@ -107,12 +109,12 @@ class SubsetProxy {
107109

108110
SubsetProxy& operator=(const SubsetProxy& other) {
109111
if (other.indices_n == 1) {
110-
for (int i=0; i < indices_n; ++i) {
112+
for (R_xlen_t i=0; i < indices_n; ++i) {
111113
lhs[ indices[i] ] = other.lhs[other.indices[0]];
112114
}
113115
}
114116
else if (indices_n == other.indices_n) {
115-
for (int i=0; i < indices_n; ++i)
117+
for (R_xlen_t i=0; i < indices_n; ++i)
116118
lhs[ indices[i] ] = other.lhs[other.indices[i]];
117119
}
118120
else {
@@ -132,34 +134,40 @@ class SubsetProxy {
132134
private:
133135

134136
#ifndef RCPP_NO_BOUNDS_CHECK
135-
void check_indices(int* x, int n, int size) {
136-
for (int i=0; i < n; ++i) {
137+
template <typename IDX>
138+
void check_indices(IDX* x, R_xlen_t n, R_xlen_t size) {
139+
for (IDX i=0; i < n; ++i) {
137140
if (x[i] < 0 or x[i] >= size) {
141+
if(std::numeric_limits<IDX>::is_integer && size > std::numeric_limits<IDX>::max()) {
142+
stop("use NumericVector to index an object of this size");
143+
}
138144
stop("index error");
139145
}
140146
}
141147
}
142148
#else
143-
void check_indices(int* x, int n, int size) {}
149+
template <typename IDX>
150+
void check_indices(IDX* x, IDX n, IDX size) {}
144151
#endif
145152

146153
void get_indices( traits::identity< traits::int2type<INTSXP> > t ) {
147154
indices.reserve(rhs_n);
148-
int* ptr = INTEGER(rhs);
155+
int* ptr = INTEGER(rhs); // ok to use int * here, we'll catch any problems inside check_indices
149156
check_indices(ptr, rhs_n, lhs_n);
150-
for (int i=0; i < rhs_n; ++i) {
157+
for (R_xlen_t i=0; i < rhs_n; ++i) {
151158
indices.push_back( rhs[i] );
152159
}
153160
indices_n = rhs_n;
154161
}
155162

156163
void get_indices( traits::identity< traits::int2type<REALSXP> > t ) {
157164
indices.reserve(rhs_n);
158-
Vector<INTSXP, StoragePolicy> tmp =
159-
as< Vector<INTSXP, StoragePolicy> >(rhs);
160-
int* ptr = INTEGER(tmp);
161-
check_indices(ptr, rhs_n, lhs_n);
162-
for (int i=0; i < rhs_n; ++i) {
165+
std::vector<R_xlen_t> tmp(rhs.size()); // create temp R_xlen_t type indices from reals
166+
for(size_t i = 0 ; i < tmp.size() ; ++i) {
167+
tmp[i] = rhs[i];
168+
}
169+
check_indices(&tmp[0], rhs_n, lhs_n);
170+
for (R_xlen_t i=0; i < rhs_n; ++i) {
163171
indices.push_back( tmp[i] );
164172
}
165173
indices_n = rhs_n;
@@ -171,7 +179,7 @@ class SubsetProxy {
171179
if (Rf_isNull(names)) stop("names is null");
172180
SEXP* namesPtr = STRING_PTR(names);
173181
SEXP* rhsPtr = STRING_PTR(rhs);
174-
for (int i = 0; i < rhs_n; ++i) {
182+
for (R_xlen_t i = 0; i < rhs_n; ++i) {
175183
SEXP* match = std::find(namesPtr, namesPtr + lhs_n, *(rhsPtr + i));
176184
if (match == namesPtr + lhs_n)
177185
stop("not found");
@@ -186,7 +194,7 @@ class SubsetProxy {
186194
stop("logical subsetting requires vectors of identical size");
187195
}
188196
int* ptr = LOGICAL(rhs);
189-
for (int i=0; i < rhs_n; ++i) {
197+
for (R_xlen_t i=0; i < rhs_n; ++i) {
190198
if (ptr[i] == NA_INTEGER) {
191199
stop("can't subset using a logical vector with NAs");
192200
}
@@ -199,13 +207,13 @@ class SubsetProxy {
199207

200208
Vector<RTYPE, StoragePolicy> get_vec() const {
201209
Vector<RTYPE, StoragePolicy> output = no_init(indices_n);
202-
for (int i=0; i < indices_n; ++i) {
210+
for (R_xlen_t i=0; i < indices_n; ++i) {
203211
output[i] = lhs[ indices[i] ];
204212
}
205213
SEXP names = Rf_getAttrib(lhs, R_NamesSymbol);
206214
if (!Rf_isNull(names)) {
207215
Shield<SEXP> out_names( Rf_allocVector(STRSXP, indices_n) );
208-
for (int i=0; i < indices_n; ++i) {
216+
for (R_xlen_t i=0; i < indices_n; ++i) {
209217
SET_STRING_ELT(out_names, i, STRING_ELT(names, indices[i]));
210218
}
211219
Rf_setAttrib(output, R_NamesSymbol, out_names);
@@ -216,13 +224,13 @@ class SubsetProxy {
216224

217225
LHS_t& lhs;
218226
const RHS_t& rhs;
219-
int lhs_n;
220-
int rhs_n;
227+
R_xlen_t lhs_n;
228+
R_xlen_t rhs_n;
221229

222-
std::vector<int> indices;
230+
std::vector<R_xlen_t> indices;
223231

224232
// because of the above, we keep track of the size
225-
int indices_n;
233+
R_xlen_t indices_n;
226234

227235
public:
228236

@@ -234,10 +242,10 @@ class SubsetProxy {
234242
RHS_NA_OTHER, RHS_T_OTHER>& other) { \
235243
Vector<RTYPE, StoragePolicy> result(indices_n); \
236244
if (other.indices_n == 1) { \
237-
for (int i = 0; i < indices_n; ++i) \
245+
for (R_xlen_t i = 0; i < indices_n; ++i) \
238246
result[i] = lhs[indices[i]] __OPERATOR__ other.lhs[other.indices[0]]; \
239247
} else if (indices_n == other.indices_n) { \
240-
for (int i = 0; i < indices_n; ++i) \
248+
for (R_xlen_t i = 0; i < indices_n; ++i) \
241249
result[i] = lhs[indices[i]] __OPERATOR__ other.lhs[other.indices[i]]; \
242250
} else { \
243251
stop("index error"); \

0 commit comments

Comments
 (0)