1+ name : Sanitizer Tests
2+
3+ # Run on main branch pushes, pull requests, and manual trigger
4+ on :
5+ push :
6+ branches : [ main ]
7+ pull_request :
8+ workflow_dispatch :
9+
10+ env :
11+ CMAKE_VERSION : 3.21.7
12+ NINJA_VERSION : 1.11.0
13+
14+ jobs :
15+ sanitizers :
16+ name : ${{ matrix.config.name }}
17+ runs-on : ${{ matrix.config.os }}
18+ strategy :
19+ fail-fast : false
20+ matrix :
21+ config :
22+ # GCC 14 with AddressSanitizer + UndefinedBehaviorSanitizer
23+ - {
24+ name : " Linux GCC 14 + ASan + UBSan" ,
25+ os : ubuntu-24.04,
26+ build_type : RelWithDebInfo,
27+ cc : " gcc-14" , cxx: "g++-14",
28+ cxx_standard : 23
29+ }
30+
31+ # Clang 18 with AddressSanitizer + UndefinedBehaviorSanitizer
32+ - {
33+ name : " Linux Clang 18 + ASan + UBSan (libc++)" ,
34+ os : ubuntu-24.04,
35+ build_type : RelWithDebInfo,
36+ cc : " clang-18" , cxx: "clang++-18",
37+ cxx_standard : 23,
38+ use_libcxx : true
39+ }
40+
41+ # Clang 21 with AddressSanitizer + UndefinedBehaviorSanitizer
42+ - {
43+ name : " Linux Clang 21 + ASan + UBSan (libc++)" ,
44+ os : ubuntu-24.04,
45+ build_type : RelWithDebInfo,
46+ cc : " clang-21" , cxx: "clang++-21",
47+ cxx_standard : 23,
48+ use_libcxx : true
49+ }
50+
51+ steps :
52+ - uses : actions/checkout@master
53+
54+ - name : Download Ninja and CMake
55+ id : cmake_and_ninja
56+ shell : cmake -P {0}
57+ run : |
58+ set(cmake_version $ENV{CMAKE_VERSION})
59+ set(ninja_version $ENV{NINJA_VERSION})
60+
61+ message(STATUS "Using host CMake version: ${CMAKE_VERSION}")
62+
63+ set(ninja_suffix "linux.zip")
64+ set(cmake_suffix "linux-x86_64.tar.gz")
65+ set(cmake_dir "cmake-${cmake_version}-linux-x86_64/bin")
66+
67+ set(ninja_url "https://github.com/ninja-build/ninja/releases/download/v${ninja_version}/ninja-${ninja_suffix}")
68+ file(DOWNLOAD "${ninja_url}" ./ninja.zip SHOW_PROGRESS)
69+ execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./ninja.zip)
70+
71+ set(cmake_url "https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-${cmake_suffix}")
72+ file(DOWNLOAD "${cmake_url}" ./cmake.zip SHOW_PROGRESS)
73+ execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf ./cmake.zip)
74+
75+ # Save the path for other steps
76+ file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/${cmake_dir}" cmake_dir)
77+ message("::set-output name=cmake_dir::${cmake_dir}")
78+
79+ execute_process(
80+ COMMAND chmod +x ninja
81+ COMMAND chmod +x ${cmake_dir}/cmake
82+ )
83+
84+ - name : Install Clang and libc++ (C++23 support)
85+ id : install_clang
86+ if : contains(matrix.config.cxx, 'clang++')
87+ shell : bash
88+ run : |
89+ # Extract version number from compiler name (e.g., clang++-21 -> 21)
90+ CLANG_VERSION=$(echo "${{ matrix.config.cxx }}" | grep -oP '\d+')
91+
92+ # Add LLVM repository for newer versions (18 is pre-installed)
93+ if [[ "$CLANG_VERSION" != "18" ]]; then
94+ wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
95+ sudo add-apt-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${CLANG_VERSION} main"
96+ fi
97+
98+ sudo apt-get update
99+
100+ # Install Clang and libc++ for the specific version
101+ sudo apt-get -y install \
102+ clang-${CLANG_VERSION} \
103+ libc++-${CLANG_VERSION}-dev \
104+ libc++abi-${CLANG_VERSION}-dev
105+
106+ - name : Install vcpkg
107+ id : vcpkg
108+ shell : bash
109+ run : |
110+ mkdir -p ${GITHUB_WORKSPACE}/vcpkg
111+ cd ${GITHUB_WORKSPACE}/vcpkg
112+ git init
113+ git remote add origin https://github.com/microsoft/vcpkg.git
114+ git fetch origin master
115+ git checkout -b master origin/master
116+ ./bootstrap-vcpkg.sh
117+
118+ # For Clang builds, use custom triplet with libc++ and set compiler
119+ if [[ "${{ matrix.config.use_libcxx }}" == "true" ]]; then
120+ export CC=${{ matrix.config.cc }}
121+ export CXX=${{ matrix.config.cxx }}
122+ ./vcpkg install uni-algo \
123+ --triplet x64-linux-libcxx \
124+ --overlay-triplets=${GITHUB_WORKSPACE}/cmake/vcpkg-triplets
125+ else
126+ ./vcpkg install uni-algo
127+ fi
128+
129+ - name : Configure
130+ shell : cmake -P {0}
131+ run : |
132+ set(ENV{CC} ${{ matrix.config.cc }})
133+ set(ENV{CXX} ${{ matrix.config.cxx }})
134+
135+ file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/ninja" ninja_program)
136+
137+ # Determine triplet for vcpkg
138+ if ("${{ matrix.config.use_libcxx }}" STREQUAL "true")
139+ set(vcpkg_triplet "x64-linux-libcxx")
140+ set(use_libcxx ON)
141+ else()
142+ set(vcpkg_triplet "x64-linux")
143+ set(use_libcxx OFF)
144+ endif()
145+
146+ execute_process(
147+ COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
148+ -S .
149+ -B build
150+ -D CMAKE_BUILD_TYPE=${{ matrix.config.build_type }}
151+ -G Ninja
152+ -D CMAKE_MAKE_PROGRAM=${ninja_program}
153+ -D CMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
154+ -D VCPKG_TARGET_TRIPLET=${vcpkg_triplet}
155+ -D skyr_BUILD_TESTS=OFF
156+ -D skyr_BUILD_EXAMPLES=OFF
157+ -D skyr_ENABLE_SANITIZERS=ON
158+ -D skyr_BUILD_WITH_LLVM_LIBCXX=${use_libcxx}
159+ -D skyr_WARNINGS_AS_ERRORS=OFF
160+ RESULT_VARIABLE result
161+ )
162+ if (NOT result EQUAL 0)
163+ message(FATAL_ERROR "Bad exit status")
164+ endif()
165+
166+ - name : Build
167+ shell : cmake -P {0}
168+ run : |
169+ set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ")
170+
171+ file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}" ccache_basedir)
172+ set(ENV{CCACHE_BASEDIR} "${ccache_basedir}")
173+ set(ENV{CCACHE_DIR} "${ccache_basedir}/.ccache")
174+ set(ENV{CCACHE_COMPRESS} "true")
175+ set(ENV{CCACHE_COMPRESSLEVEL} "6")
176+ set(ENV{CCACHE_MAXSIZE} "400M")
177+
178+ execute_process(
179+ COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake --build build --target url_sanitizer_tests
180+ RESULT_VARIABLE result
181+ )
182+ if (NOT result EQUAL 0)
183+ message(FATAL_ERROR "Build failed")
184+ endif()
185+
186+ - name : Run Sanitizer Tests
187+ shell : bash
188+ run : |
189+ echo "========================================"
190+ echo "Running AddressSanitizer + UBSan Tests"
191+ echo "========================================"
192+
193+ # Set sanitizer options for comprehensive checking
194+ # alloc_dealloc_mismatch=0: Suppress false positive from libc++ exception handling
195+ export ASAN_OPTIONS=detect_leaks=1:check_initialization_order=1:strict_init_order=1:detect_stack_use_after_return=1:alloc_dealloc_mismatch=0:verbosity=0
196+ export UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=0
197+
198+ # Run the sanitizer test
199+ ./build/tests/sanitizers/url_sanitizer_tests
200+
201+ TEST_RESULT=$?
202+
203+ if [ $TEST_RESULT -eq 0 ]; then
204+ echo "✓ All sanitizer tests passed - no memory safety issues detected!"
205+ else
206+ echo "✗ Sanitizer tests failed or detected issues"
207+ exit 1
208+ fi
0 commit comments