Skip to content

UBSAN issue can arise when std::copy(ing) an Rcpp::NumericVector of length 0 #1461

@luisgruber

Description

@luisgruber

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions