diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7eb315db..b6840c4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,17 +27,36 @@ jobs: - uses: actions/checkout@v4 - run: npm ci - run: npm test + - name: Install clang for ASAN + run: sudo apt-get update && sudo apt-get install -y clang - name: Set up cargo cache uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 - run: cargo fmt --all -- --check - run: cargo clippy --all-targets --all-features -- -D warnings - - run: cargo test --features odbc-static + - name: Build proc-macros without ASAN first + run: cargo build --lib --features odbc-static + - name: Run tests with ASAN-instrumented C dependencies + env: + CFLAGS: "-fsanitize=address -fno-omit-frame-pointer -g" + CXXFLAGS: "-fsanitize=address -fno-omit-frame-pointer -g" + CC: clang + CXX: clang++ + RUSTFLAGS: "-Clink-arg=-fsanitize=address" + ASAN_OPTIONS: "detect_leaks=1:abort_on_error=1" + run: | + # Find and preload ASAN runtime library so rustc can load ASAN-linked proc-macros + ASAN_LIB=$(clang -print-file-name=libclang_rt.asan-x86_64.so) + export LD_PRELOAD="$ASAN_LIB" + # Recompile C dependencies and binaries with ASAN instrumentation + cargo clean -p aws-lc-sys -p libsqlite3-sys -p zstd-sys -p sqlpage + cargo test --features odbc-static - name: Upload Linux binary uses: actions/upload-artifact@v4 with: name: sqlpage-linux-debug path: "target/debug/sqlpage" + test: runs-on: ubuntu-latest strategy: diff --git a/ASAN-BUILD-PROCESS.md b/ASAN-BUILD-PROCESS.md new file mode 100644 index 00000000..d1757f05 --- /dev/null +++ b/ASAN-BUILD-PROCESS.md @@ -0,0 +1,47 @@ +# Building with ASAN for C Dependencies + +## Two-Phase Build Approach + +The solution uses a two-phase build to avoid proc-macro loading issues: + +### Phase 1: Build proc-macros without ASAN +```bash +cargo build --lib --features odbc-static +``` + +This builds all libraries and proc-macros (like `sqlx-macros-oldapi`) with normal linking. + +### Phase 2: Rebuild with ASAN instrumentation +```bash +# Set up ASAN environment +export CFLAGS="-fsanitize=address -fno-omit-frame-pointer -g" +export CXXFLAGS="-fsanitize=address -fno-omit-frame-pointer -g" +export CC=clang +export CXX=clang++ +export RUSTFLAGS="-Clink-arg=-fsanitize=address" + +# Preload ASAN runtime so rustc can load proc-macros +export LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) + +# Rebuild only C dependencies and main binary +cargo clean -p aws-lc-sys -p libsqlite3-sys -p zstd-sys -p sqlpage +cargo test --features odbc-static +``` + +## Why This Works + +1. **Proc-macros** are built first without ASAN and cached +2. **C dependencies** (aws-lc-sys, libsqlite3-sys, zstd-sys) are recompiled with ASAN instrumentation +3. **LD_PRELOAD** loads the ASAN runtime library into the cargo/rustc process, allowing it to successfully load proc-macros even if they transitively depend on ASAN-instrumented code +4. **Final binary and tests** are linked with ASAN runtime via `-Clink-arg=-fsanitize=address` + +## What Gets Detected + +With ASAN enabled for C dependencies, the tests will detect: +- Buffer overflows in C code +- Use-after-free errors in C code +- Memory leaks in C code (via LeakSanitizer) +- Stack buffer overflows +- Global buffer overflows + +This provides comprehensive memory safety checking for the native C dependencies while working around Rust's proc-macro system limitations. diff --git a/Cargo.lock b/Cargo.lock index 3d36bc87..c76d820c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -610,6 +610,15 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "autotools" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef941527c41b0fc0dd48511a8154cd5fc7e29200a0ff8b7203c5d777dbc795cf" +dependencies = [ + "cc", +] + [[package]] name = "awc" version = "3.8.1" @@ -3073,8 +3082,9 @@ dependencies = [ [[package]] name = "odbc-sys" -version = "0.27.3" -source = "git+https://github.com/sqlpage/odbc-sys?branch=no-autotools#ae3e15446bb2c5c191f05e7c6affc37dfd6fcabe" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2127e7f596b99095fe8ebb03f9fd52e32fd01a28e66eac41c1e637f963d488e" dependencies = [ "unix-odbc", ] @@ -4806,9 +4816,11 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unix-odbc" version = "0.1.2" -source = "git+https://github.com/sqlpage/odbc-sys?branch=no-autotools#ae3e15446bb2c5c191f05e7c6affc37dfd6fcabe" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed7dc665cf7dfdb5b9c1fe9c8257f053be19ecad9966090acce5f574cb2eeff" dependencies = [ - "cc", + "autotools", + "fs_extra", ] [[package]] @@ -5577,3 +5589,8 @@ dependencies = [ "cc", "pkg-config", ] + +[[patch.unused]] +name = "odbc-sys" +version = "0.27.3" +source = "git+https://github.com/sqlpage/odbc-sys?branch=no-autotools#ae3e15446bb2c5c191f05e7c6affc37dfd6fcabe"