Skip to content

Commit 63a241c

Browse files
committed
Check that sanitizer=address (libasan) is available before using it
1 parent 64a6ae1 commit 63a241c

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1818
- Refactored documentation
1919
- External libraries aren't forcibly installed via the Arduino binary (in `arduino_cmd_remote.rb`) if they appear to exist on disk already
2020
- `attachInterrupt` and `detachInterrupt` are now mocked instead of `_NOP`
21-
- Unit test binaries now run with debugging symbols and address sanitization, to help isolate the causes of segfaults
21+
- Unit test binaries now run with debugging symbols and address sanitization (if available), to help isolate the causes of segfaults
2222

2323
### Deprecated
2424

lib/arduino_ci/cpp_library.rb

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def initialize(base_dir, arduino_lib_dir)
3737
@last_err = ""
3838
@last_out = ""
3939
@last_msg = ""
40+
@has_libasan_cache = {}
4041
end
4142

4243
# Guess whether a file is part of the vendor bundle (indicating we should ignore it).
@@ -54,6 +55,24 @@ def vendor_bundle?(path)
5455
false
5556
end
5657

58+
# Check whether libasan (and by extension -fsanitizer=address) is supported
59+
#
60+
# This requires compilation of a sample program, and will be cached
61+
# @param gcc_binary
62+
def libasan?(gcc_binary)
63+
if @has_libasan_cache.nil?
64+
file = Tempfile.new('arduino_ci_libasan_check')
65+
begin
66+
file.write "int main(){}"
67+
file.close
68+
@has_libasan_cache = run_gcc(gcc_binary, "-o", "/dev/null", "-fsanitize=address", file.path)
69+
ensure
70+
file.delete
71+
end
72+
end
73+
@has_libasan_cache
74+
end
75+
5776
# Get a list of all CPP source files in a directory and its subdirectories
5877
# @param some_dir [String] The directory in which to begin the search
5978
# @return [Array<String>] The paths of the found files
@@ -216,18 +235,20 @@ def build_for_test_with_configuration(test_file, aux_libraries, gcc_binary, ci_g
216235
base = File.basename(test_file)
217236
executable = File.expand_path("unittest_#{base}.bin")
218237
File.delete(executable) if File.exist?(executable)
219-
args = [
220-
["-std=c++0x", "-o", executable, "-DARDUINO=100"],
221-
[ # Stuff to help with dynamic memory mishandling
238+
arg_sets = []
239+
arg_sets << ["-std=c++0x", "-o", executable, "-DARDUINO=100"]
240+
if libasan?(gcc_binary)
241+
arg_sets << [ # Stuff to help with dynamic memory mishandling
222242
"-g", "-O1",
223243
"-fno-omit-frame-pointer",
224244
"-fno-optimize-sibling-calls",
225245
"-fsanitize=address"
226-
],
227-
test_args(aux_libraries, ci_gcc_config),
228-
cpp_files_libraries(aux_libraries),
229-
[test_file],
230-
].flatten(1)
246+
]
247+
end
248+
arg_sets << test_args(aux_libraries, ci_gcc_config)
249+
arg_sets << cpp_files_libraries(aux_libraries)
250+
arg_sets << [test_file]
251+
args = arg_sets.flatten(1)
231252
return nil unless run_gcc(gcc_binary, *args)
232253

233254
artifacts << executable

0 commit comments

Comments
 (0)