Skip to content

Commit c755145

Browse files
authored
Add AddressSanitizer to GitHub Actions (#3959)
- Make the `qsort` test work under AddressSanitizer. See the comment added to `qsort_.c` for more details. - Add a GitHub actions build variant for testing the AddressSanitizer integration
1 parent 77ac450 commit c755145

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

.github/workflows/build.yml

+12
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ jobs:
175175
ocamlparam: '_,w=-46,regalloc=cfg,vectorize=1'
176176
check_arch: true
177177

178+
- name: address_sanitizer
179+
config: --enable-middle-end=flambda2 --enable-address-sanitizer
180+
os: ubuntu-latest
181+
cc: clang
182+
178183
env:
179184
J: "3"
180185
run_testsuite: "true"
@@ -189,6 +194,10 @@ jobs:
189194
if: matrix.os == 'ubuntu-latest'
190195
run: sudo apt-get install afl++
191196

197+
- name: Install clang
198+
if: matrix.os == 'ubuntu-latest' && matrix.cc == 'clang'
199+
run: sudo apt-get install clang
200+
192201
- name: Install AFL (for macOS workers)
193202
# The "afl-fuzz" package is deprecated (2023-10) and can no longer be installed
194203
if: matrix.os == 'macos-latest'
@@ -280,6 +289,9 @@ jobs:
280289
- name: Configure Flambda backend
281290
working-directory: flambda_backend
282291
run: |
292+
if [[ -n "${{matrix.cc}}" ]]; then
293+
export CC="${{matrix.cc}}"
294+
fi
283295
autoconf
284296
./configure \
285297
--prefix=$GITHUB_WORKSPACE/_install \

testsuite/tests/frame-pointers/qsort.ml

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
(* TEST
22
modules = "qsort_.c";
3+
(* [-D_GNU_SOURCE] is needed when AddressSanitizer support is enabled in order
4+
for the [dlsym] workaround in [qsort_.c] to work. *)
5+
flags = "-ccopt -D_GNU_SOURCE";
36
frame_pointers;
47
{
58
bytecode;

testsuite/tests/frame-pointers/qsort_.c

+22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
#define CAML_NAME_SPACE
2+
#include <caml/config.h>
3+
#ifdef WITH_ADDRESS_SANITIZER
4+
#include <dlfcn.h>
5+
#endif
26
#include <caml/memory.h>
37
#include <caml/mlvalues.h>
48
#include <caml/alloc.h>
@@ -71,6 +75,24 @@ static int cmp_callback(const void* p_a, const void* p_b)
7175
return Long_val(caml_callback2(*cmp_fn, **a, **b));
7276
}
7377

78+
#ifdef WITH_ADDRESS_SANITIZER
79+
/* AddressSanitizer provides its own definition of [qsort], which runs the comparator
80+
function over the entire array in order to detect memory safety issues [1].
81+
That breaks this test, since the output of the test depends on how many times the
82+
comparator function is invoked. To work around this, we retrieve the standard [qsort]
83+
definition provided by [libc] using [dlsym], and call that directly.
84+
85+
[1]: https://github.com/llvm/llvm-project/blob/1101b767329dd163d528fa5f667a6c0dbdde0ad5/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc#L10047-L10051
86+
*/
87+
void qsort(void *base, size_t nmemb, size_t size, __compar_fn_t compar) {
88+
static void (*libc_qsort)(void *, size_t, size_t, __compar_fn_t) = NULL;
89+
if (libc_qsort == NULL) {
90+
libc_qsort = dlsym(RTLD_NEXT, "qsort");
91+
}
92+
libc_qsort(base, nmemb, size, compar);
93+
}
94+
#endif
95+
7496
value sort2(value cmp_clos, value a, value b)
7597
{
7698
CAMLparam3(cmp_clos, a, b);

0 commit comments

Comments
 (0)