[R-pkg-devel] Fwd: CRAN Submission rkriging 1.0.1
Ivan Krylov
|kry|ov @end|ng |rom d|@root@org
Thu Jul 18 13:29:03 CEST 2024
Hi Chaofan and welcome to R-package-devel!
В Wed, 17 Jul 2024 11:52:53 -0700
Bill Huang <10billhuang01 using gmail.com> пишет:
> The package can be installed successfully locally and passed CRAN
> auto-check. However, it cannot pass the gcc-UBSAN test with the
> following error message: a problem with the LLT function in Eigen. I
> am not sure how to fix this.
The problem is detected by special, normally disabled instrumentation
called UBSanitizer [1]. If you don't want to compile R with sanitizers
enabled yourself, ready-made Docker/Podman containers
rocker-org/r-devel-san and rocker-org/r-devel-san-clang [2] (and
others, there are sanitizer containers published by the R-hub
project as well) should help you reproduce the problem.
In this case, I suspect that you stumbled upon a problem in Eigen
itself: the Eigen::LLT constructor does not initialise an enumeration
field, ComputationInfo m_info, which results in the field being
populated by something out of range of the enumeration, which invokes
undefined behaviour.
You can reproduce the problem without building an R package at all:
#include <iostream>
#include <Eigen>
struct foo : Eigen::LLT<Eigen::MatrixXd> {
foo() : Eigen::LLT<Eigen::MatrixXd>(42) {
// m_info is protected, hence use of inheritance
std::cout << m_info << std::endl;
}
};
int main() {
foo L;
}
g++ -fsanitize=undefined -g -Og -I $LIBRARY/RcppEigen/include/Eigen \
-o ex ex.cpp
./ex
# ex.cpp:7:16: runtime error: load of value 32608, which is not a valid
# value for type 'ComputationInfo'
# 32608
A workaround for the problem is to move the initialization of the
Eigen::LLT<Eigen::MatrixXd> Kriging::L_ field from the constructor body
into the member initializer list:
--- rkriging.orig/src/kriging.cpp 2024-07-04 06:45:57.000000000 +0300
+++ rkriging/src/kriging.cpp 2024-07-18 14:10:54.000000000 +0300
@@ -20,10 +20,9 @@
return kriging->get_nllh(log_lengthscale, nugget);
}
-Kriging::Kriging(const Eigen::MatrixXd& X, const Eigen::VectorXd& y, Kernel& Ker, const bool& interpolation): n_(X.rows()), p_(X.cols()), X_(X), y_(y), Ker_(Ker), interpolation_(interpolation) {
+Kriging::Kriging(const Eigen::MatrixXd& X, const Eigen::VectorXd& y, Kernel& Ker, const bool& interpolation): n_(X.rows()), p_(X.cols()), X_(X), y_(y), Ker_(Ker), interpolation_(interpolation), L_(n_) {
a_.resize(n_);
b_.resize(n_);
- L_ = Eigen::LLT<Eigen::MatrixXd>(n_);
y_tss_ = y_.squaredNorm() - std::pow(y_.sum(),2)/n_;
nugget_ = interpolation_ ? 1e-6 : 1e-3;
nllh_ = std::numeric_limits<double>::infinity();
This seems to avoid poking the bear of undefined behaviour with
potential copying of invalid enum value in L_ until something
initialises it properly.
I'm not sure whether this is worth reporting to Eigen as something to
fix. I hope that people here with more experience in C++ and Eigen will
be able to answer that question.
--
Best regards,
Ivan
[1]
https://cran.r-project.org/doc/manuals/R-exts.html#Using-Undefined-Behaviour-Sanitizer
[2]
https://rocker-project.org/images/base/r-devel.html
More information about the R-package-devel
mailing list