Repository navigation
UBSAN issue can arise when std::copy(ing) an Rcpp::NumericVector of length 0 #1461
Copy link
Copy link
Closed
Description
Testing a package I am contributing to (gregorkastner/factorstochvol) triggered UBSAN using the clang-ubsan r-hub container.
The problem occurs when I std::copy() an Rcpp::NumericVector of length 0. Here is a minimal reproducible example which triggers the error:
$ podman run --rm -ti --pull=newer ghcr.io/r-hub/containers/clang-ubsan
root@bf478e112875:/# R
> pak::pak("Rcpp")
> sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void fun_rcpp(R_xlen_t p) {
NumericVector vec1(p);
NumericVector vec2(p);
Rcout << vec2.begin() << "\\n";
std::copy(vec1.begin(), vec1.end(), vec2.begin());
}')
> fun_rcpp(0)
0x1
/usr/lib/llvm-22/bin/../include/c++/v1/__string/constexpr_c_functions.h:227:25: runtime error: store to misaligned address 0x000000000001 for type 'double *', which requires 8 byte alignment
0x000000000001: note: pointer points here
<memory cannot be printed>
#0 0x7398a95b6e5a in double* std::__1::__constexpr_memmove[abi:nqe220103]<double, double>(double*, double*, std::__1::__element_count) /usr/lib/llvm-22/bin/../include/c++/v1/__string/constexpr_c_functions.h:227:5
#1 0x7398a95b6e5a in std::__1::pair<double*, double*> std::__1::__copy_trivial_impl[abi:nqe220103]<double, double>(double*, double*, double*) /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy_move_common.h:64:3
#2 0x7398a95b6e5a in std::__1::pair<double*, double*> std::__1::__copy_impl::operator()[abi:nqe220103]<double, double, 0>(double*, double*, double*) const /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy.h:115:12
#3 0x7398a95b6e5a in std::__1::pair<double*, double*> std::__1::__copy_move_unwrap_iters[abi:nqe220103]<std::__1::__copy_impl, double*, double*, double*, 0>(double*, double*, double*) /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy_move_common.h:94:19
#4 0x7398a95b5cc0 in std::__1::pair<double*, double*> std::__1::__copy[abi:nqe220103]<double*, double*, double*>(double*, double*, double*) /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy.h:122:10
#5 0x7398a95b5cc0 in double* std::__1::copy[abi:nqe220103]<double*, double*>(double*, double*, double*) /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy.h:128:10
#6 0x7398a95b5cc0 in fun_rcpp(long) /tmp/RtmphbrcTn/sourceCpp-x86_64-pc-linux-gnu-1.1.1/sourcecpp_81dde26d/file81296eccf.cpp:9:3
#7 0x7398a95b5e19 in sourceCpp_3_fun_rcpp /tmp/RtmphbrcTn/sourceCpp-x86_64-pc-linux-gnu-1.1.1/sourcecpp_81dde26d/file81296eccf.cpp:25:5
#8 0x7798b1fc3480 in R_doDotCall /tmp/R-devel/src/main/dotcode.c:754:11
#9 0x7798b1fc506d in do_dotcall /tmp/R-devel/src/main/dotcode.c:1437:11
#10 0x7798b1ffa906 in Rf_eval /tmp/R-devel/src/main/eval.c:1260:9
#11 0x7798b1ffb127 in Rf_evalList /tmp/R-devel/src/main/eval.c:3679:12
#12 0x7798b1ffa800 in Rf_eval /tmp/R-devel/src/main/eval.c:1251:20
#13 0x7798b1ffd308 in R_execClosure /tmp/R-devel/src/main/eval.c:2389:39
#14 0x7798b1ffbf3b in applyClosure_core /tmp/R-devel/src/main/eval.c:2302:16
#15 0x7798b1ffa985 in Rf_applyClosure /tmp/R-devel/src/main/eval.c:2324:16
#16 0x7798b1ffa985 in Rf_eval /tmp/R-devel/src/main/eval.c:1280:12
#17 0x7798b20490d7 in Rf_ReplIteration /tmp/R-devel/src/main/main.c:264:23
#18 0x7798b204a72e in R_ReplConsole /tmp/R-devel/src/main/main.c:317:11
#19 0x7798b204a72e in run_Rmainloop /tmp/R-devel/src/main/main.c:1235:5
#20 0x7798b204a79a in Rf_mainloop /tmp/R-devel/src/main/main.c:1242:5
#21 0x5a9917129c27 in main /tmp/R-devel/src/main/Rmain.c:29:5
#22 0x7798b1a5ad8f (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 095c7ba148aeca81668091f718047078d57efddb)
#23 0x7798b1a5ae3f in __libc_start_main (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 095c7ba148aeca81668091f718047078d57efddb)
#24 0x5a9917040384 in _start (/opt/R/devel-asan/lib/R/bin/exec/R+0x2d384) (BuildId: 6b2bb379dec6fd1104eb4971c90488e20a001ded)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/llvm-22/bin/../include/c++/v1/__string/constexpr_c_functions.h:227:25
/usr/lib/llvm-22/bin/../include/c++/v1/__string/constexpr_c_functions.h:227:33: runtime error: load of misaligned address 0x000000000001 for type 'double *', which requires 8 byte alignment
0x000000000001: note: pointer points here
<memory cannot be printed>
#0 0x7398a95b6e74 in double* std::__1::__constexpr_memmove[abi:nqe220103]<double, double>(double*, double*, std::__1::__element_count) /usr/lib/llvm-22/bin/../include/c++/v1/__string/constexpr_c_functions.h:227:5
#1 0x7398a95b6e74 in std::__1::pair<double*, double*> std::__1::__copy_trivial_impl[abi:nqe220103]<double, double>(double*, double*, double*) /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy_move_common.h:64:3
#2 0x7398a95b6e74 in std::__1::pair<double*, double*> std::__1::__copy_impl::operator()[abi:nqe220103]<double, double, 0>(double*, double*, double*) const /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy.h:115:12
#3 0x7398a95b6e74 in std::__1::pair<double*, double*> std::__1::__copy_move_unwrap_iters[abi:nqe220103]<std::__1::__copy_impl, double*, double*, double*, 0>(double*, double*, double*) /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy_move_common.h:94:19
#4 0x7398a95b5cc0 in std::__1::pair<double*, double*> std::__1::__copy[abi:nqe220103]<double*, double*, double*>(double*, double*, double*) /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy.h:122:10
#5 0x7398a95b5cc0 in double* std::__1::copy[abi:nqe220103]<double*, double*>(double*, double*, double*) /usr/lib/llvm-22/bin/../include/c++/v1/__algorithm/copy.h:128:10
#6 0x7398a95b5cc0 in fun_rcpp(long) /tmp/RtmphbrcTn/sourceCpp-x86_64-pc-linux-gnu-1.1.1/sourcecpp_81dde26d/file81296eccf.cpp:9:3
#7 0x7398a95b5e19 in sourceCpp_3_fun_rcpp /tmp/RtmphbrcTn/sourceCpp-x86_64-pc-linux-gnu-1.1.1/sourcecpp_81dde26d/file81296eccf.cpp:25:5
#8 0x7798b1fc3480 in R_doDotCall /tmp/R-devel/src/main/dotcode.c:754:11
#9 0x7798b1fc506d in do_dotcall /tmp/R-devel/src/main/dotcode.c:1437:11
#10 0x7798b1ffa906 in Rf_eval /tmp/R-devel/src/main/eval.c:1260:9
#11 0x7798b1ffb127 in Rf_evalList /tmp/R-devel/src/main/eval.c:3679:12
#12 0x7798b1ffa800 in Rf_eval /tmp/R-devel/src/main/eval.c:1251:20
#13 0x7798b1ffd308 in R_execClosure /tmp/R-devel/src/main/eval.c:2389:39
#14 0x7798b1ffbf3b in applyClosure_core /tmp/R-devel/src/main/eval.c:2302:16
#15 0x7798b1ffa985 in Rf_applyClosure /tmp/R-devel/src/main/eval.c:2324:16
#16 0x7798b1ffa985 in Rf_eval /tmp/R-devel/src/main/eval.c:1280:12
#17 0x7798b20490d7 in Rf_ReplIteration /tmp/R-devel/src/main/main.c:264:23
#18 0x7798b204a72e in R_ReplConsole /tmp/R-devel/src/main/main.c:317:11
#19 0x7798b204a72e in run_Rmainloop /tmp/R-devel/src/main/main.c:1235:5
#20 0x7798b204a79a in Rf_mainloop /tmp/R-devel/src/main/main.c:1242:5
#21 0x5a9917129c27 in main /tmp/R-devel/src/main/Rmain.c:29:5
#22 0x7798b1a5ad8f (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 095c7ba148aeca81668091f718047078d57efddb)
#23 0x7798b1a5ae3f in __libc_start_main (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 095c7ba148aeca81668091f718047078d57efddb)
#24 0x5a9917040384 in _start (/opt/R/devel-asan/lib/R/bin/exec/R+0x2d384) (BuildId: 6b2bb379dec6fd1104eb4971c90488e20a001ded)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/lib/llvm-22/bin/../include/c++/v1/__string/constexpr_c_functions.h:227:33
With std::vector<double> instead of Rcpp::NumericVector the error will not occur:
> sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void fun_std(size_t p) {
std::vector<double> vec1(p);
std::vector<double> vec2(p);
auto x = vec2.begin();
Rcout << reinterpret_cast<const void*>(&x) << "\\n";
std::copy(vec1.begin(), vec1.end(), vec2.begin());
}')
> fun_std(0)
0x7ffc96ba38d0
sessionInfo
> sessionInfo()
R Under development (unstable) (2026-03-25 r89703)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 22.04.5 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so; LAPACK version 3.10.0
locale:
[1] LC_CTYPE=en_GB.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_GB.UTF-8 LC_COLLATE=C
[5] LC_MONETARY=en_GB.UTF-8 LC_MESSAGES=en_GB.UTF-8
[7] LC_PAPER=en_GB.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C
time zone: Etc/UTC
tzcode source: system (glibc)
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] Rcpp_1.1.1
loaded via a namespace (and not attached):
[1] compiler_4.6.0 tools_4.6.0 pak_0.9.2.9000
Interestingly, using docker.io/rocker/r-devel-ubsan-clang instead of the r-hub container does not trigger the error.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
eddelbuettel commentedon Mar 26, 2026
Thanks for reproducible example. I suggest to work more with
std::vector<>or the differentarma::vecor to check the length :)Kidding aside, this may be tricky to address: note how your trace swings from your
fun_rcppdirectly into the standard library.luisgruber commentedon Mar 26, 2026
Thanks for the fast reply. Yes, I will definitely add checking the length in the package code under question. Still, I was keen to hear an expert opinion on this behavior, since it's well beyond my programming skills.
eddelbuettel commentedon Mar 26, 2026
It's (likely, have not checked yet) heavily templated code so (to a first approximation) 'nobody' understands it. The compile-time and run-time interactions can be tricky as 'length zero' sits squarely with the latter. Adding a simple check somewhere is likely a solution, not unlike the UBSAN issue you discovered recenty with Armadillo (and which despite the initial sound and fury coming from the direction of Brisbane was addressed upstream, huffing and puffing about 'false positives' notwithstanding...).
luisgruber commentedon Mar 26, 2026
Wow, you guys are really fast, you already fixed the issue!
Concerning the UBSAN Armadillo thingy: Kudos @haansn08 for discovering it!
eddelbuettel commentedon Mar 26, 2026
See @kevinushey 's comment on the PR. As you have a replicating setup ready, can you check if it actually helps or creates new issues?
luisgruber commentedon Mar 26, 2026
It seems to help: It does not trigger the error anymore!