├── lastBuild.txt ├── .github └── workflows │ └── docker.yaml ├── README.md └── Dockerfile /lastBuild.txt: -------------------------------------------------------------------------------- 1 | 2025-12-16 04:20:16+00:00 2 | -------------------------------------------------------------------------------- /.github/workflows/docker.yaml: -------------------------------------------------------------------------------- 1 | name: docker 2 | 3 | on: 4 | push: 5 | schedule: 6 | - cron: "22 2 * * 2" 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | 17 | #- name: Set up QEMU 18 | # uses: docker/setup-qemu-action@v1 19 | 20 | - name: Buildx 21 | uses: docker/setup-buildx-action@v2 22 | 23 | - name: Login 24 | uses: docker/login-action@v2 25 | with: 26 | username: ${{ secrets.DOCKER_USERNAME }} 27 | password: ${{ secrets.DOCKER_PASSWORD }} 28 | 29 | - name: Build and push 30 | uses: docker/build-push-action@v4 31 | with: 32 | context: . 33 | push: true 34 | tags: rocker/r-devel-ubsan-clang:latest 35 | 36 | - name: Timestamp 37 | run: date --rfc-3339=seconds > lastBuild.txt 38 | 39 | - name: Commit and push 40 | uses: EndBug/add-and-commit@v9 41 | with: 42 | add: "lastBuild.txt" 43 | push: true 44 | default_author: github_actions 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## R-devel SAN using Clang: R development binaries with Sanitizer support 3 | 4 | The [Writing R Extensions manual](http://cran.r-project.org/doc/manuals/r-devel/R-exts.html) details 5 | in [Section 4.3](http://cran.r-project.org/doc/manuals/r-devel/R-exts.html#Checking-memory-access) 6 | how to check memory access. Two sections are devoted to [Using the Address 7 | Sanitizer](http://cran.r-project.org/doc/manuals/r-devel/R-exts.html#Using-Address-Sanitizer) and to 8 | [Using the Undefined Behaviour 9 | Sanitizer](http://cran.r-project.org/doc/manuals/r-devel/R-exts.html#Using-Undefined-Behaviour-Sanitizer). 10 | 11 | Both require a particularly instrumented binary of R. This repository provides a Docker container 12 | with such a binary, based on the R-devel sources. 13 | 14 | This repository uses clang; a [sibling repository](https://github.com/rocker-org/r-devel-san) uses 15 | gcc. 16 | 17 | **Note**: At least under some Docker versions, this container must be run with `docker run --cap-add 18 | SYS_PTRACE`, otherwise instrumented processes fail to start due to lacking 19 | permissions. Alternatively, an instrumented process can be run with `ASAN_OPTIONS=detect_leaks=0`, 20 | but this turns off leak detection. 21 | 22 | Note that the instrumented version of `R` is available on the path as `Rdevel`, symbolically linked 23 | as `RD`, and that the instrumented versions of `Rscript` is `Rscriptdevel` with symbolic link 24 | `RDscript`. Based on the R-devel sources, they use the sanitizer setup that is the focuse here 25 | whereas the `R` and `Rscript` binaries come from the standard binary package and correspond to 26 | R-release *without* any sanitizer instrumentation. So use `RD` and `RDscript` to inspect undefined 27 | behavior. 28 | 29 | The [sanitiziers](https://github.com/eddelbuettel/sanitizers) package by 30 | [Dirk](https://github.com/eddelbuettel) (also on CRAN 31 | [here](https://cran.r-project.org/web/packages/sanitizers/index.html)) contains 'known bad' behavior 32 | detected by sanitizers, It can be used to validate the setup as it should detect the errors under 33 | `RD` and `RDscript`---but not under `R` and `Rscript` which are not instrumented. If in doubt, use 34 | this to familiarise yourself with the sanitizer behavior. 35 | 36 | The (newer, larger) [r-debug](https://github.com/wch/r-debug) by [Winston](https://github.com/wch/) 37 | is also available with even more build configs and is also recommended. 38 | 39 | ## Rocker-Org 40 | 41 | This repository is part of [Rocker-Org](https://github.com/rocker-org) where 42 | [Rocker](https://github.com/rocker-org/rocker) -- Docker containers of 43 | interest for R users -- is being developed. 44 | 45 | All this is work in progress; talk to [Dirk](https://github.com/eddelbuettel) or 46 | [Carl](https://github.com/cboettig) about how to get involved. 47 | 48 | Documentation is being added at the [Rocker Wiki](https://github.com/rocker-org/rocker/wiki). 49 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ## Emacs, make this -*- mode: sh; -*- 2 | 3 | ## start with the Docker 'base R' Debian-based image 4 | FROM r-base:latest 5 | 6 | LABEL org.label-schema.license="GPL-2.0" \ 7 | org.label-schema.vcs-url="https://github.com/rocker-org/" \ 8 | org.label-schema.vendor="Rocker Project" \ 9 | maintainer="Dirk Eddelbuettel " 10 | 11 | ## Remain current 12 | RUN apt update -qq \ 13 | && apt dist-upgrade -y 14 | 15 | ## From the Build-Depends of the Debian R package, plus subversion, and clang-3.8 16 | ## Compiler flags from https://www.stats.ox.ac.uk/pub/bdr/memtests/README.txt 17 | ## 18 | ## Also add git autotools-dev automake so that we can build littler from source 19 | ## libclang-rt-16-dev now required 20 | ## 21 | RUN apt update -qq \ 22 | && apt install -t unstable -y --no-install-recommends \ 23 | automake \ 24 | autotools-dev \ 25 | bash-completion \ 26 | bison \ 27 | clang \ 28 | libc++-dev \ 29 | libc++abi-dev \ 30 | debhelper \ 31 | default-jdk \ 32 | gfortran \ 33 | git \ 34 | groff-base \ 35 | libblas-dev \ 36 | libbz2-dev \ 37 | libcairo2-dev \ 38 | libclang-rt-dev \ 39 | libclang-rt-21-dev \ 40 | libcurl4-openssl-dev \ 41 | libjpeg-dev \ 42 | liblapack-dev \ 43 | liblzma-dev \ 44 | libncurses-dev \ 45 | libpango1.0-dev \ 46 | libpcre2-dev \ 47 | libpng-dev \ 48 | libreadline-dev \ 49 | libssl-dev \ 50 | libtiff5-dev \ 51 | libx11-dev \ 52 | libxml2-dev \ 53 | libxt-dev \ 54 | llvm \ 55 | mpack \ 56 | subversion \ 57 | tcl-dev \ 58 | texinfo \ 59 | texlive-base \ 60 | texlive-extra-utils \ 61 | texlive-fonts-extra \ 62 | texlive-fonts-recommended \ 63 | texlive-plain-generic \ 64 | texlive-latex-base \ 65 | texlive-latex-extra \ 66 | texlive-latex-recommended \ 67 | tk-dev \ 68 | valgrind \ 69 | x11proto-core-dev \ 70 | xauth \ 71 | xdg-utils \ 72 | xfonts-base \ 73 | xvfb \ 74 | zlib1g-dev \ 75 | && rm -rf /var/lib/apt/lists/* 76 | 77 | ## Add symlink and check out R-devel 78 | RUN ln -s $(which llvm-symbolizer-7) /usr/local/bin/llvm-symbolizer \ 79 | && cd /tmp \ 80 | && svn co https://svn.r-project.org/R/trunk R-devel 81 | 82 | ## Build and install according extending the standard 'recipe' I emailed/posted years ago 83 | ## Leak detection does not work at build time, see https://github.com/google/sanitizers/issues/764 and the fact that we cannot add privileges during build (e.g. https://unix.stackexchange.com/q/329816/19205) 84 | RUN cd /tmp/R-devel \ 85 | && which clang \ 86 | && clang --version \ 87 | && R_PAPERSIZE=letter \ 88 | R_BATCHSAVE="--no-save --no-restore" \ 89 | R_BROWSER=xdg-open \ 90 | PAGER=/usr/bin/pager \ 91 | PERL=/usr/bin/perl \ 92 | R_UNZIPCMD=/usr/bin/unzip \ 93 | R_ZIPCMD=/usr/bin/zip \ 94 | R_PRINTCMD=/usr/bin/lpr \ 95 | LIBnn=lib \ 96 | AWK=/usr/bin/awk \ 97 | CC="clang -fsanitize=address,undefined -fno-sanitize=float-divide-by-zero -fno-sanitize=alignment -fno-omit-frame-pointer" \ 98 | CXX="clang++ -fsanitize=address,undefined -fno-sanitize=float-divide-by-zero -fno-sanitize=alignment -fno-omit-frame-pointer -frtti" \ 99 | CFLAGS="-g -O3 -Wall -pedantic" \ 100 | FFLAGS="-g -O2 -mtune=native" \ 101 | CXXFLAGS="-g -O3 -Wall -pedantic" \ 102 | MAIN_LD="clang++ -fsanitize=undefined,address" \ 103 | FC="gfortran" \ 104 | F77="gfortran" \ 105 | ASAN_OPTIONS=detect_leaks=0 \ 106 | ./configure --enable-R-shlib \ 107 | --without-blas \ 108 | --without-lapack \ 109 | --with-readline \ 110 | --without-recommended-packages \ 111 | --program-suffix=dev \ 112 | --disable-openmp \ 113 | && ASAN_OPTIONS=detect_leaks=0 make \ 114 | && ASAN_OPTIONS=detect_leaks=0 make install \ 115 | && ASAN_OPTIONS=detect_leaks=0 make clean 116 | 117 | ## Set Renviron to get libs from base R install 118 | RUN echo "R_LIBS=\${R_LIBS-'/usr/local/lib/R/site-library:/usr/local/lib/R/library:/usr/lib/R/library'}" >> /usr/local/lib/R/etc/Renviron 119 | 120 | ## Set default CRAN repo 121 | RUN echo 'options("repos"="http://cran.rstudio.com")' >> /usr/local/lib/R/etc/Rprofile.site 122 | 123 | ## to also build littler against RD 124 | ## 1) apt-get install git autotools-dev automake 125 | ## 2) use CC from RD CMD config CC, ie same as R 126 | ## 3) use PATH to include RD's bin, ie 127 | ## ie 128 | ## CC="clang-3.5 -fsanitize=undefined -fno-sanitize=float-divide-by-zero,vptr,function -fno-sanitize-recover" \ 129 | ## PATH="/usr/local/lib/R/bin/:$PATH" \ 130 | ## ./bootstrap 131 | 132 | ## Create R-devel symlinks 133 | RUN cd /usr/local/bin \ 134 | && mv R Rdevel \ 135 | && mv Rscript Rscriptdevel \ 136 | && ln -s Rdevel RD \ 137 | && ln -s Rscriptdevel RDscript 138 | 139 | ## Install littler 140 | RUN ASAN_OPTIONS='detect_leaks=0' R --slave -e "install.packages('littler')" \ 141 | && ASAN_OPTIONS='detect_leaks=0' RD --slave -e "install.packages('littler')" 142 | 143 | CMD ["bash"] 144 | --------------------------------------------------------------------------------