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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions