From 523cf6b5edb46babac9534bfb0299858d5bd63b7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 20 Oct 2025 17:24:20 +0000 Subject: [PATCH 1/3] Add ASAN CI job and documentation Co-authored-by: contact --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ ASAN-NOTES.md | 40 ++++++++++++++++++++++++++++++++++++++++ Cargo.lock | 25 +++++++++++++++++++++---- 3 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 ASAN-NOTES.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7eb315db..9526c9bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,30 @@ jobs: name: sqlpage-linux-debug path: "target/debug/sqlpage" + test_asan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - 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 + - name: Build 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++ + run: cargo build --features odbc-static + - name: Run tests with ASAN + env: + ASAN_OPTIONS: "detect_leaks=1:abort_on_error=1" + CFLAGS: "-fsanitize=address -fno-omit-frame-pointer -g" + CXXFLAGS: "-fsanitize=address -fno-omit-frame-pointer -g" + CC: clang + CXX: clang++ + run: cargo test --features odbc-static --no-fail-fast + test: runs-on: ubuntu-latest strategy: diff --git a/ASAN-NOTES.md b/ASAN-NOTES.md new file mode 100644 index 00000000..3a8f7c8e --- /dev/null +++ b/ASAN-NOTES.md @@ -0,0 +1,40 @@ +# Address Sanitizer (ASAN) Configuration + +## C Dependencies with ASAN + +This project successfully compiles C dependencies with ASAN enabled: +- aws-lc-sys (AWS-LC crypto library) +- libsqlite3-sys (SQLite) +- zstd-sys (Zstandard compression) +- unix-odbc (when using odbc-static feature) + +### Configuration + +The C dependencies are compiled with ASAN using these environment variables: +```bash +export CFLAGS="-fsanitize=address -fno-omit-frame-pointer -g" +export CXXFLAGS="-fsanitize=address -fno-omit-frame-pointer -g" +export CC=clang +export CXX=clang++ +``` + +A custom linker wrapper ensures ASAN runtime is linked: +```bash +#!/bin/bash +exec clang -fsanitize=address "$@" +``` + +### Known Limitation: Proc-Macros with `-Zbuild-std` + +Enabling full Rust ASAN (`-Zsanitizer=address`) with `-Zbuild-std` causes issues with proc-macro crates. +The sqlx-oldapi dependency uses sqlx-macros-oldapi (a proc-macro), which cannot be loaded when +the standard library is rebuilt with ASAN. + +## Workaround for Testing + +For CI/testing purposes, we can: +1. Compile C dependencies with ASAN only (catches memory issues in native code) +2. Run tests with ASAN enabled to detect memory errors +3. Use LeakSanitizer (LSAN) in addition to catch memory leaks + +This provides significant value as the C dependencies are where most memory safety issues occur. 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" From dfb210dccabd8efd5d33d9771995ec699eabc2d6 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 20 Oct 2025 22:08:51 +0000 Subject: [PATCH 2/3] Remove ASAN test job and documentation Co-authored-by: contact --- .github/workflows/ci.yml | 23 ----------------------- ASAN-NOTES.md | 40 ---------------------------------------- 2 files changed, 63 deletions(-) delete mode 100644 ASAN-NOTES.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9526c9bb..34371fd8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,29 +38,6 @@ jobs: name: sqlpage-linux-debug path: "target/debug/sqlpage" - test_asan: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - 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 - - name: Build 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++ - run: cargo build --features odbc-static - - name: Run tests with ASAN - env: - ASAN_OPTIONS: "detect_leaks=1:abort_on_error=1" - CFLAGS: "-fsanitize=address -fno-omit-frame-pointer -g" - CXXFLAGS: "-fsanitize=address -fno-omit-frame-pointer -g" - CC: clang - CXX: clang++ - run: cargo test --features odbc-static --no-fail-fast test: runs-on: ubuntu-latest diff --git a/ASAN-NOTES.md b/ASAN-NOTES.md deleted file mode 100644 index 3a8f7c8e..00000000 --- a/ASAN-NOTES.md +++ /dev/null @@ -1,40 +0,0 @@ -# Address Sanitizer (ASAN) Configuration - -## C Dependencies with ASAN - -This project successfully compiles C dependencies with ASAN enabled: -- aws-lc-sys (AWS-LC crypto library) -- libsqlite3-sys (SQLite) -- zstd-sys (Zstandard compression) -- unix-odbc (when using odbc-static feature) - -### Configuration - -The C dependencies are compiled with ASAN using these environment variables: -```bash -export CFLAGS="-fsanitize=address -fno-omit-frame-pointer -g" -export CXXFLAGS="-fsanitize=address -fno-omit-frame-pointer -g" -export CC=clang -export CXX=clang++ -``` - -A custom linker wrapper ensures ASAN runtime is linked: -```bash -#!/bin/bash -exec clang -fsanitize=address "$@" -``` - -### Known Limitation: Proc-Macros with `-Zbuild-std` - -Enabling full Rust ASAN (`-Zsanitizer=address`) with `-Zbuild-std` causes issues with proc-macro crates. -The sqlx-oldapi dependency uses sqlx-macros-oldapi (a proc-macro), which cannot be loaded when -the standard library is rebuilt with ASAN. - -## Workaround for Testing - -For CI/testing purposes, we can: -1. Compile C dependencies with ASAN only (catches memory issues in native code) -2. Run tests with ASAN enabled to detect memory errors -3. Use LeakSanitizer (LSAN) in addition to catch memory leaks - -This provides significant value as the C dependencies are where most memory safety issues occur. From ed9771b302f09f0219bde7b56db65d6b0b764864 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 21 Oct 2025 06:47:38 +0000 Subject: [PATCH 3/3] feat: Enable ASAN for C dependencies in CI Co-authored-by: contact --- .github/workflows/ci.yml | 20 ++++++++++++++++- ASAN-BUILD-PROCESS.md | 47 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 ASAN-BUILD-PROCESS.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34371fd8..b6840c4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,11 +27,29 @@ 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: 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.