Skip to content

Commit e3d9c22

Browse files
committed
Add sanitizer functionality (ASAN, LSAN, UBSAN) support
This change adds sanitizer toolchain functionality, which can help identify issues within the lutok codebase. Introduce GH action to run the tests with UBSAN enabled. Initial scaffolding for ASAN/LSAN support is added, but not enabled via GHA. Issues blocking its enablement are discussed more at length in freebsd/atf#77. Related to: freebsd/atf#177 Signed-off-by: Enji Cooper <ngie@FreeBSD.org>
1 parent 5c0de2d commit e3d9c22

7 files changed

Lines changed: 228 additions & 72 deletions

File tree

‎.github/workflows/build.yaml‎

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
# * Run tests
1111
#
1212
# On MacOS we build with:
13-
# * latest clang from brew (system provided clang lacks sanitizers).
14-
# * ld from system
13+
# * latest clang from brew (system provided clang lacks sanitizers).
14+
# * ld from system
1515
name: build
16-
on: # yamllint disable-line rule:truthy
16+
"on":
1717
pull_request:
1818
branches:
1919
- master
@@ -24,20 +24,22 @@ permissions:
2424
contents: read
2525

2626
jobs:
27-
build:
28-
name: build ${{ matrix.build-os }} ${{ matrix.compiler }}
27+
build-and-test:
28+
# yamllint disable-line rule:line-length
29+
name: ${{ matrix.build-os }} ${{ matrix.compiler }} ${{ join(matrix.sanitize, '+') }}
2930
env:
3031
AR: ${{ matrix.llvm-bindir }}/llvm-ar
3132
CC: ${{ matrix.llvm-bindir }}/clang
3233
CPP: ${{ matrix.llvm-bindir }}/clang-cpp
3334
CXX: ${{ matrix.llvm-bindir }}/clang++
3435
NM: ${{ matrix.llvm-bindir }}/llvm-nm
35-
RANLIB: ${{ matrix.llvm-bindir }}/llvm-ranlib
3636
OBJDUMP: ${{ matrix.llvm-bindir }}/llvm-objdump
37+
RANLIB: ${{ matrix.llvm-bindir }}/llvm-ranlib
3738
STRIP: ${{ matrix.llvm-bindir }}/llvm-strip
3839
LUTOK_SRCDIR: ${{ github.workspace }}/src
3940
LUTOK_OBJDIR: ${{ github.workspace }}/obj
40-
JOB_NAME: ${{ matrix.build-os }} ${{ matrix.compiler }}
41+
# yamllint disable-line rule:line-length
42+
JOB_NAME: ${{ matrix.build-os }} ${{ matrix.compiler }} ${{ join(matrix.sanitize, '+') }}
4143
runs-on: "${{ matrix.build-os }}"
4244
strategy:
4345
fail-fast: false
@@ -67,16 +69,23 @@ jobs:
6769
- atf-sh
6870
- autoconf
6971
- automake
72+
- clang-18
7073
- doxygen
7174
- graphviz
7275
- kyua
7376
- libatf-dev
7477
- liblua5.4-dev
7578
- libtool
76-
- llvm-18
7779
- lua5.4
7880
- pkgconf
7981
llvm-bindir: /usr/lib/llvm-18/bin
82+
sanitize:
83+
- ""
84+
# TODO(ngie,77): tests currently fail when these options
85+
# are enabled.
86+
# - ["asan", "lsan"]
87+
- ubsan
88+
8089
steps:
8190
- name: Install packages (macOS)
8291
if: runner.os == 'macOS'
@@ -97,14 +106,26 @@ jobs:
97106
- name: Sanity checks
98107
run: |
99108
which -a kyua
100-
- name: Build
109+
- name: Configure
101110
run: |
111+
CFG_ARGS="--enable-atf"
112+
for i in ${{ join(matrix.sanitize, ' ') }}; do
113+
CFG_ARGS="${CFG_ARGS} --enable-${i}"
114+
done
115+
echo "uname -a: $(uname -a)"
116+
echo "uname -m: $(uname -m)"
117+
echo "uname -p: $(uname -p)"
118+
echo "Build environment:"
119+
kyua about | head -1
120+
102121
cd "${LUTOK_SRCDIR}"
103-
./admin/ci-build/01_configure.sh
122+
./admin/ci-build/01_configure.sh ${CFG_ARGS}
104123
- name: Distcheck (builds and tests)
105124
run: |
106-
CFG_ARGS="--disable-dependency-tracking --enable-developer"
107-
CFG_ARGS="${CFG_ARGS} --enable-atf"
125+
CFG_ARGS="--disable-dependency-tracking --enable-atf"
126+
for i in ${{ join(matrix.sanitize, ' ') }}; do
127+
CFG_ARGS="${CFG_ARGS} --enable-${i}"
128+
done
108129
cd "${LUTOK_SRCDIR}"
109130
env "EXTRA_DISTCHECK_CONFIGURE_ARGS=${CFG_ARGS}" \
110131
./admin/ci-build/02_distcheck.sh

‎INSTALL.md‎

Lines changed: 70 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ need the following tools:
4646
* GNU Automake 1.9 (or later).
4747
* GNU Libtool.
4848

49-
5049
# Regenerating the build system
5150

5251
This is not necessary if you are building from a formal release
@@ -102,66 +101,94 @@ To build and install the source package, you must follow these steps:
102101
The most common, standard flags given to `configure` are:
103102

104103
- `--prefix=directory`
105-
- **Possible values**: any path
106-
- **Default**: "/usr/local"
107104

108-
Specifies where the library (binaries and all associated files) will
109-
be installed.
105+
**Possible values**: any path
106+
**Default**: "/usr/local"
110107

111-
- `--help`
112-
Shows information about all available flags and exits immediately,
113-
without running any configuration tasks.
108+
Specifies where the library (binaries and all associated files) will be
109+
installed.
114110

115111
The following flags are specific to Lutok's `configure` script:
116112

117-
- `--enable-developer`
118-
- **Possible values**: "yes", "no"
119-
- **Default**: "yes" in Git HEAD builds; "no" in formal releases.
113+
- `--enable-developer`:
114+
115+
**Default:** `yes` in HEAD builds; `no` in release builds.
116+
117+
Enables several features useful for development, such as the inclusion
118+
of debugging symbols in all objects or the enforcement of compilation
119+
warnings.
120+
121+
The compiler will be executed with an exhaustive collection of warning
122+
detection features regardless of the value of this flag. However, such
123+
warnings are only fatal when `--enable-developer` is `yes`.
120124

121-
Enables several features useful for development, such as the inclusion
122-
of debugging symbols in all objects or the enforcement of compilation
123-
warnings.
125+
- `--enable-asan`
124126

125-
The compiler will be executed with an exhaustive collection of warning
126-
detection features regardless of the value of this flag. However, such
127-
warnings are only fatal when `--enable-developer` is set to "yes".
127+
**Default:** `no`.
128+
129+
Enables ASAN (Address Sanitizer) compiler support in the toolchain.
130+
131+
Platform-specific support varies depending on the toolchain and OS.
128132

129133
- `--enable-atf`
130-
- **Possible values**: "yes", "no", "auto".
131-
- **Default**: "auto"
132134

133-
Enables usage of ATF to build (and later install) the tests.
135+
**Possible values**: "yes", "no", "auto".
136+
**Default**: "auto"
137+
138+
Enables usage of ATF to build (and later install) the tests.
139+
140+
Setting this to "yes" causes the `configure` script to look for ATF
141+
unconditionally and abort if not found. Setting this to "auto" lets
142+
`configure` perform the best decision based on availability of ATF.
143+
Setting this to "no" explicitly disables ATF usage.
144+
145+
When support for tests is enabled, the build process will generate the
146+
test programs and will later install them into the tests tree.
147+
Running `make check` or `make installcheck` from within the source
148+
directory will cause these tests to be run with Kyua (assuming it is
149+
also installed).
150+
151+
- `--enable-lsan`
152+
153+
**Default:** `no`.
154+
155+
Enables LSAN (Leak Sanitizer) compiler support in the toolchain.
156+
157+
Platform-specific support varies depending on the toolchain and OS.
158+
159+
**Important:**
160+
* llvm support is only available in Linux and macOS at time of writing.
161+
* The test suite does not currently pass with this option enabled. See
162+
[Issue #77](https://github.com/freebsd/atf/issues/77) for more details.
163+
164+
- `--enable-ubsan`
165+
166+
**Default:** `no`.
134167

135-
Setting this to "yes" causes the `configure` script to look for ATF
136-
unconditionally and abort if not found. Setting this to "auto" lets
137-
`configure` perform the best decision based on availability of ATF.
138-
Setting this to "no" explicitly disables ATF usage.
168+
Enables UBSAN (Undefined Behavior Sanitizier) compiler support in the
169+
toolchain.
139170

140-
When support for tests is enabled, the build process will generate the
141-
test programs and will later install them into the tests tree.
142-
Running `make check` or `make installcheck` from within the source
143-
directory will cause these tests to be run with Kyua (assuming it is
144-
also installed).
171+
Platform-specific support varies depending on the toolchain and OS.
145172

146173
- `--with-doxygen`
147-
- **Possible values**: "yes", "no", "auto", or a path.
148-
- **Default**: "auto".
149174

150-
Enables usage of Doxygen to generate documentation for internal APIs.
175+
**Possible values**: "yes", "no", "auto", or a path.
176+
**Default**: "auto".
151177

152-
Setting this to "yes" causes the `configure` script to look for Doxygen
153-
unconditionally and abort if not found. Setting this to "auto" lets
154-
`configure` perform the best decision based on availability of Doxygen.
155-
Setting this to "no" explicitly disables Doxygen usage. And, lastly,
156-
setting this to a path forces `configure` to use a specific Doxygen
157-
binary, which must exist.
178+
Enables usage of Doxygen to generate documentation for internal APIs.
158179

159-
When support for Doxygen is enabled, the build process will generate
160-
HTML documentation for the Lutok API. This documentation will later
161-
be installed in the HTML directory specified by the `configure` script.
162-
You can change the location of the HTML documents by providing your
163-
desired override with the `--htmldir` flag to the `configure` script.
180+
Setting this to "yes" causes the `configure` script to look for Doxygen
181+
unconditionally and abort if not found. Setting this to "auto" lets
182+
`configure` perform the best decision based on availability of Doxygen.
183+
Setting this to "no" explicitly disables Doxygen usage. And, lastly,
184+
setting this to a path forces `configure` to use a specific Doxygen
185+
binary, which must exist.
164186

187+
When support for Doxygen is enabled, the build process will generate
188+
HTML documentation for the Lutok API. This documentation will later
189+
be installed in the HTML directory specified by the `configure` script.
190+
You can change the location of the HTML documents by providing your
191+
desired override with the `--htmldir` flag to the `configure` script.
165192

166193
Run the tests!
167194
==============

‎Makefile.am‎

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,28 @@
2626
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2727
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828

29+
#
30+
# Supporting logic to run our custom testsuite.
31+
#
32+
33+
TESTS_ENVIRONMENT = PKG_CONFIG_PATH=$(prefix)/lib/pkgconfig
34+
35+
if HAVE_ASAN
36+
# NB: the trailing comma is intentional. I hate automake not allowing `:=` use on subsequent lines.
37+
if HAVE_LSAN
38+
LSAN_OPTIONS = detect_leaks=1,
39+
else
40+
LSAN_OPTIONS =
41+
endif
42+
# Some of the testcases trigger false positives as they pass
43+
# `SIZE_MAX - 1`, etc, to malloc(3).
44+
ASAN_OPTIONS = ${LSAN_OPTIONS}allocator_may_return_null=1
45+
TESTS_ENVIRONMENT+= ASAN_OPTIONS=${ASAN_OPTIONS}
46+
endif
47+
if HAVE_UBSAN
48+
TESTS_ENVIRONMENT+= UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1
49+
endif
50+
2951
ACLOCAL_AMFLAGS = -I m4
3052

3153
doc_DATA = AUTHORS COPYING NEWS README.md
@@ -80,6 +102,8 @@ lutok.pc: $(srcdir)/lutok.pc.in Makefile
80102
-e 's#__LIBDIR__#$(libdir)#g' \
81103
-e 's#__LUA_CFLAGS__#$(LUA_CFLAGS)#g' \
82104
-e 's#__LUA_LIBS__#$(LUA_LIBS)#g' \
105+
-e 's#__PC_CXXFLAGS__#$(pc_cxxflags)#g' \
106+
-e 's#__PC_LDFLAGS__#$(pc_ldflags)#g' \
83107
-e 's#__VERSION__#$(PACKAGE_VERSION)#g' \
84108
<$(srcdir)/lutok.pc.in >lutok.pc.tmp; \
85109
mv lutok.pc.tmp lutok.pc
@@ -143,19 +167,38 @@ state_test_SOURCES = state_test.cpp test_utils.hpp
143167
state_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS)
144168
state_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS)
145169

146-
if HAVE_KYUA
147-
TESTS_ENVIRONMENT = PKG_CONFIG_PATH=$(prefix)/lib/pkgconfig
148-
149170
check-local: check-kyua
150171
PHONY_TARGETS += check-kyua
151172
check-kyua:
152173
$(TESTS_ENVIRONMENT) kyua test \
153174
--kyuafile='$(top_srcdir)/Kyuafile' --build-root='$(top_builddir)'
154175

176+
INSTALLCHECK_TARGETS =
177+
178+
testsdir = $(exec_prefix)/tests
179+
pkgtestsdir = $(testsdir)/$(PACKAGE)
180+
155181
installcheck-local: installcheck-kyua
156182
PHONY_TARGETS += installcheck-kyua
183+
if HAVE_KYUA
184+
185+
INSTALLCHECK_TARGETS += installcheck-kyua
186+
157187
installcheck-kyua:
158-
cd $(testsdir) && $(TESTS_ENVIRONMENT) kyua test
188+
set +e; cd $(pkgtestsdir) && $(TESTS_ENVIRONMENT) \
189+
$(KYUA) --config='$(KYUA_TEST_CONFIG_FILE)' test; \
190+
ret=$$?; \
191+
echo $$ret; \
192+
if [ -n "$$JUNIT_OUTPUT" ]; then \
193+
cd $(pkgtestsdir) && $(TESTS_ENVIRONMENT) \
194+
$(KYUA) --config='$(KYUA_TEST_CONFIG_FILE)' \
195+
report-junit --output="$$JUNIT_OUTPUT"; \
196+
sed -i '.orig' 's/encoding="iso-8859-1"/encoding="utf-8"/' "$$JUNIT_OUTPUT"; \
197+
rm -f "$$JUNIT_OUTPUT.orig"; \
198+
fi; \
199+
cd $(pkgtestsdir) && $(TESTS_ENVIRONMENT) \
200+
$(KYUA) --config='$(KYUA_TEST_CONFIG_FILE)' report --verbose; \
201+
exit $$ret
159202
endif
160203
else
161204
DIST_HOOKS += dist-no-atf
@@ -220,4 +263,6 @@ clean-all:
220263

221264
dist-hook: $(DIST_HOOKS)
222265

223-
.PHONY: ${PHONY_TARGETS}
266+
.PHONY: $(PHONY_TARGETS)
267+
268+
# vim: syntax=make:noexpandtab:shiftwidth=8:softtabstop=8

‎admin/ci-build/01_configure.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fi
1717
# shellcheck disable=SC2086
1818
autoreconf ${autoreconf_args}
1919

20-
if ! ./configure --enable-atf; then
20+
if ! ./configure $*; then
2121
cat config.log || true
2222
exit 1
2323
fi

‎admin/ci-build/02_distcheck.sh‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ set -eux
1919
NPROC=$(nproc 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null || echo 1)
2020

2121
f="--enable-atf"
22-
f="${f} ATF_BUILD_CC='${CC}'"
23-
f="${f} ATF_BUILD_CXX='${CXX}'"
24-
# Is this being run in a git clone, or with a release artifact?
22+
# Is this being run in a git clone, or with a release artifact? If the former,
23+
# automatically enable developer mode.
2524
if git rev-parse --is-inside-work-tree; then
2625
f="${f} --enable-developer"
2726
fi
@@ -47,4 +46,4 @@ ${sudo} env PATH="${PATH}" make distcheck -j"${NPROC}" \
4746
DISTCHECK_CONFIGURE_FLAGS="${f}" \
4847
KYUA_TEST_CONFIG_FILE="${kyua_conf}"
4948

50-
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4
49+
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4:textwidth=80

0 commit comments

Comments
 (0)