summaryrefslogtreecommitdiff
path: root/tools/ci/inria/extra-checks
blob: 9e2afc4aae01f423ed5d262b37155d535285128e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/bin/sh
#**************************************************************************
#*                                                                        *
#*                                 OCaml                                  *
#*                                                                        *
#*      Damien Doligez, Xavier Leroy, projet Gallium, INRIA Paris         *
#*                                                                        *
#*   Copyright 2018 Institut National de Recherche en Informatique et     *
#*     en Automatique.                                                    *
#*                                                                        *
#*   All rights reserved.  This file is distributed under the terms of    *
#*   the GNU Lesser General Public License version 2.1, with the          *
#*   special exception on linking described in the file LICENSE.          *
#*                                                                        *
#**************************************************************************

# This script is run on Inria's continuous-integration servers to recompile
# from scratch, adding more run-time checks ("sanitizers") to the C code,
# and run the test suite.

# In this context, it is necessary to skip a few tests whose behaviour
# is modified by the instrumentation:

export OCAMLTEST_SKIP_TESTS="tests/afl-instrumentation/afltest.ml \
tests/runtime-errors/stackoverflow.ml"

# To know the slave's architecture, this script looks at the OCAML_ARCH
# environment variable. For a given node NODE, this variable can be defined
# in Jenkins at the following address:
# https://ci.inria.fr/ocaml/computer/NODE/configure

# Other environment variables that are honored:
#   OCAML_JOBS                number of jobs to run in parallel (make -j)

# Command-line arguments:
# -jNN                    pass "-jNN" option to make for parallel builds

error () {
  echo "$1" >&2
  exit 3
}

arch_error() {
  configure_url="https://ci.inria.fr/ocaml/computer/${NODE_NAME}/configure"
  msg="Unknown architecture. Make sure the OCAML_ARCH environment"
  msg="$msg variable has been defined."
  msg="$msg\nSee ${configure_url}"
  error "$msg"
}

# Change a variable in Makefile.config
# Usage: set_config_var <variable name> <new value>


set_config_var() {
  conffile=Makefile.config
  mv ${conffile} ${conffile}.bak
  (grep -v "^$1=" ${conffile}.bak; echo "$1=$2") > ${conffile}
}

#########################################################################
# stop on error
set -e

# be considerate towards other potential users of the test machine
case "${OCAML_ARCH}" in
  bsd|macos|linux) renice 10 $$ ;;
esac

# set up variables

make=make
jobs=''

case "${OCAML_ARCH}" in
  bsd) make=gmake ;;
  macos) ;;
  linux) ;;
  cygwin|cygwin64|mingw|mingw64|msvc|msvc64)
    error "Don't run this test under Windows";;
  *) arch_error;;
esac

case "${OCAML_JOBS}" in
  [1-9]|[1-9][0-9]) jobs="-j${OCAML_JOBS}" ;;
esac

# parse optional command-line arguments

while [ $# -gt 0 ]; do
  case $1 in
    -j[1-9]|-j[1-9][0-9]) jobs="$1";;
    *) error "unknown option $1";;
  esac
  shift
done

# Tell gcc to use only ASCII in its diagnostic outputs.
export LC_ALL=C

# How to run the test suite
if test -n "$jobs" && test -x /usr/bin/parallel; then
  export PARALLEL="$jobs $PARALLEL"
  run_testsuite="$make -C testsuite parallel"
else
  run_testsuite="$make -C testsuite all"
fi

# A tool that make error backtrace nicer
# Need to pick the one that matches clang-6.0 and is named "llvm-symbolizer"
# (/usr/bin/llvm-symbolizer-6.0 doesn't work, that would be too easy)
export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer
export TSAN_SYMBOLIZER_PATH="$ASAN_SYMBOLIZER_PATH"

#########################################################################

# Ensure that the repo still passes the check-typo script
if [ ! -x tools/check-typo ] ; then
  error "tools/check-typo does not appear to be executable?"
fi
tools/check-typo

#########################################################################

echo "======== old school build =========="

git clean -q -f -d -x

instdir="$HOME/ocaml-tmp-install-$$"
./configure --prefix "$instdir"

# Build the system without using world.opt
make $jobs world
make $jobs opt
make $jobs opt.opt
make install

rm -rf "$instdir"

# It's a build system test only, so we don't bother testing the compiler

#########################################################################

echo "======== clang 6.0, address sanitizer, UB sanitizer =========="

git clean -q -f -d -x

# Use clang 6.0
# We cannot give the sanitizer options as part of -cc because
# then various autoconfiguration tests fail.
# Instead, we'll fix OC_CFLAGS a posteriori.
./configure CC=clang-6.0

# These are the undefined behaviors we want to check
# Others occur on purpose e.g. signed arithmetic overflow
ubsan="\
bool,\
builtin,\
bounds,\
enum,\
nonnull-attribute,\
nullability,\
object-size,\
pointer-overflow,\
returns-nonnull-attribute,\
shift-exponent,\
unreachable"

# Select address sanitizer and UB sanitizer, with trap-on-error behavior
# Don't optimize too much to get better backtraces of errors
set_config_var OC_CFLAGS "-O1 \
-fno-strict-aliasing -fwrapv -fno-omit-frame-pointer \
-Wall -Werror \
-fsanitize=address \
-fsanitize-trap=$ubsan"

# Build the system.  We want to check for memory leaks, hence
# 1- force ocamlrun to free memory before exiting
# 2- add an exception for ocamlyacc, which doesn't free memory

OCAMLRUNPARAM="c=1" \
LSAN_OPTIONS="suppressions=$(pwd)/tools/ci/inria/lsan-suppr.txt" \
make $jobs world.opt

# Run the testsuite.
# We deactivate leak detection for two reasons:
# - The suppressed leak detections related to ocamlyacc mess up the
# output of the tests and are reported as failures by ocamltest.
# - The Ocaml runtime does not free the memory when a fatal error
# occurs.

# We already use sigaltstack for stack overflow detection. Our use
# interracts with ASAN's. Hence, we tell ASAN not to use it.

ASAN_OPTIONS="detect_leaks=0,use_sigaltstack=0" $run_testsuite

#########################################################################

echo "======== clang 6.0, thread sanitizer =========="

git clean -q -f -d -x

./configure CC=clang-6.0

# Select thread sanitizer
# Don't optimize too much to get better backtraces of errors
set_config_var OC_CFLAGS "-O1 \
-fno-strict-aliasing -fwrapv -fno-omit-frame-pointer \
-Wall -Werror \
-fsanitize=thread"

# Build the system
make $jobs world.opt

# Run the testsuite.
# ThreadSanitizer complains about fork() in threaded programs,
# we ask it to just continue in this case.
TSAN_OPTIONS="die_after_fork=0" $run_testsuite

#########################################################################

# This is a failed attempt at using the memory sanitizer
# (to detect reads from uninitialized memory).
# Some alarms are reported that look like false positive
# and are impossible to debug.

# echo "======== clang 6.0, memory sanitizer =========="

# git clean -q -f -d -x

# # Use clang 6.0
# # We cannot give the sanitizer options as part of -cc because
# # then various autoconfiguration tests fail.
# # Instead, we'll fix OC_CFLAGS a posteriori.
# # Memory sanitizer doesn't like the static data generated by ocamlopt,
# # hence build bytecode only
# ./configure CC=clang-6.0 --disable-native-compiler

# # Select memory sanitizer
# # Don't optimize at all to get better backtraces of errors
# set_config_var OC_CFLAGS "-O0 -g \
# -fno-strict-aliasing -fwrapv -fno-omit-frame-pointer \
# -Wall -Werror \
# -fsanitize=memory"

# # A tool that make error backtrace nicer
# # Need to pick the one that matches clang-6.0
# export MSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer

# # Build the system (bytecode only) and test
# make $jobs world
# $run_testsuite