-
Notifications
You must be signed in to change notification settings - Fork 41
Patch integer overflow in 'Rcpp::wrap(<Eigen::Matrix>)' #105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Nice. I'll give this as a good look. |
Do you think you can cook up an example or test ? (bad and wrong math deleted) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me -- added some whitespace changes and a ChangeLog entry
Sorry about the whitespace. Probably an Emacs glitch on my end, since it looked fine in my buffer. Here is a basic test - I only have 16 GB RAM myself... Rcpp::sourceCpp(code = '
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
Rcpp::IntegerVector vector_wrap(R_xlen_t n) {
Eigen::VectorXi x(n, 1);
for (R_xlen_t i = 0; i < n; ++i) {
x(i) = (int) (i % 10);
}
return Rcpp::wrap(x);
}
// [[Rcpp::export]]
Rcpp::IntegerMatrix matrix_wrap(R_xlen_t n) {
Eigen::MatrixXi x(n, 1);
for (R_xlen_t i = 0; i < n; ++i) {
x(i, 0) = (int) (i % 10);
}
return Rcpp::wrap(x);
}
')
gc(FALSE)
n <- floor(2^31.5)
x <- vector_wrap(n)
stopifnot(is.vector(x, "integer"),
length(x) == n,
identical(x[seq_len(2^10)], rep_len(0:9, 2^10)))
rm(x)
gc(FALSE)
h <- function(cond) grepl("INT_MAX", conditionMessage(cond))
stopifnot(tryCatch({matrix_wrap(n); FALSE}, error = h)) |
Hehe, I use Emacs too. See the (old) first line in the file; these days I prefer Maybe my math was wrong but I try to convince myself we need more. Oh, but now I know what my error was. Better way:
|
Yep, works well here too. Matrix case does not error. Was it supposed to? |
I expect |
Well played -- because that error-throwing was not in your code I didn't run it so I didn't see it. Concur on what the test script does. And maybe today isn't just my day -- but a vector of size N should have the same memory requirement as an N x 1 matrix. What am I missing? |
Memory isn't really the problem. The The constraint on
and also discussed in |
You are spot on, and I once knew that by heart too. With That is actually a really nice on. We could add that the unit tests, possibly behind another opt-in boolean toggle (just how |
R_xlen_t m = obj.rows(), n = obj.cols(), size = m * n; | ||
SEXP ans = PROTECT(::Rcpp::wrap(objCopy.data(), objCopy.data() + size)); | ||
if ( T::ColsAtCompileTime != 1 ) { | ||
if (m > INT_MAX || n > INT_MAX) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be immediately after the dimension definition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes... I've just committed again to my fork to address that, but it won't appear here until the PR is reopened. (I think?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tacking on: Is objCopy
really a copy of obj
? Why do we need objCopy.data()
here, rather than obj.data()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that it may needs a cleanup as the Rcpp:;stop()
also breaks the protect/unprotect dance.
The const T& obj
to <.... const T&>::type objCopy(obj)
dance is likely due to some TMP magic we need.
I'll move the check up a line now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my latest commit, unless you are suggesting something different?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see no commits, this has been merged to the repo. See the purple 'Merged' button here.
Note that I also just committed so if you want to change relative to the repo you need to update your for by pulling the main repo here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your change seems perfectly fine - I often forget how GitHub works past midnight... Glad this was caught and fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh - I spoke too soon. See my PR #106.
Fixes integer overflow bug detected here so that
Rcpp::wrap(<Eigen::Matrix>)
actually supports long vectors.