From 0b169453ebcee054a9fcc39e83a36079660cbafe Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 19:18:04 +0800 Subject: [PATCH 01/10] chore: cleanup codes --- src/simd/avx2.rs | 30 +++++++++++++++-------------- src/simd/avx512.rs | 30 +++++++++++++++-------------- src/simd/neon.rs | 32 ++++++++++++++++--------------- src/simd/sse2.rs | 34 ++++++++++++++++---------------- src/simd/v128.rs | 48 ++++++++++++++++++++++++++-------------------- 5 files changed, 94 insertions(+), 80 deletions(-) diff --git a/src/simd/avx2.rs b/src/simd/avx2.rs index 94a4546..03164aa 100644 --- a/src/simd/avx2.rs +++ b/src/simd/avx2.rs @@ -220,25 +220,27 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { // Handle remaining bytes let mut placeholder: [u8; LANES] = [0; LANES]; while nb > 0 { - #[cfg(not(any(target_os = "linux", target_os = "macos")))] let v = { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd256u::loadu(placeholder.as_ptr()) - }; - #[cfg(any(target_os = "linux", target_os = "macos"))] - let v = { - if check_cross_page(sptr, LANES) { + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd256u::loadu(placeholder.as_ptr()) - } else { - #[cfg(any(debug_assertions, miri))] - { + } + #[cfg(any(target_os = "linux", target_os = "macos"))] + { + if check_cross_page(sptr, LANES) { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd256u::loadu(placeholder.as_ptr()) - } - #[cfg(not(any(debug_assertions, miri)))] - { - Simd256u::loadu(sptr) + } else { + #[cfg(any(debug_assertions, miri))] + { + std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); + Simd256u::loadu(placeholder.as_ptr()) + } + #[cfg(not(any(debug_assertions, miri)))] + { + Simd256u::loadu(sptr) + } } } }; diff --git a/src/simd/avx512.rs b/src/simd/avx512.rs index c6ad65c..9aaf80b 100644 --- a/src/simd/avx512.rs +++ b/src/simd/avx512.rs @@ -212,25 +212,27 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { // Handle remaining bytes let mut placeholder: [u8; LANES] = [0; LANES]; while nb > 0 { - #[cfg(not(any(target_os = "linux", target_os = "macos")))] let v = { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd512u::loadu(placeholder.as_ptr()) - }; - #[cfg(any(target_os = "linux", target_os = "macos"))] - let v = { - if check_cross_page(sptr, LANES) { + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd512u::loadu(placeholder.as_ptr()) - } else { - #[cfg(any(debug_assertions, miri))] - { + } + #[cfg(any(target_os = "linux", target_os = "macos"))] + { + if check_cross_page(sptr, LANES) { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd512u::loadu(placeholder.as_ptr()) - } - #[cfg(not(any(debug_assertions, miri)))] - { - Simd512u::loadu(sptr) + } else { + #[cfg(any(debug_assertions, miri))] + { + std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); + Simd512u::loadu(placeholder.as_ptr()) + } + #[cfg(not(any(debug_assertions, miri)))] + { + Simd512u::loadu(sptr) + } } } }; diff --git a/src/simd/neon.rs b/src/simd/neon.rs index c3e1f85..fce9224 100644 --- a/src/simd/neon.rs +++ b/src/simd/neon.rs @@ -219,27 +219,29 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { } // Handle remaining bytes - let mut placeholder: [u8; 16] = [0; 16]; + let mut placeholder: [u8; LANES] = [0; LANES]; while nb > 0 { - #[cfg(not(any(target_os = "linux", target_os = "macos")))] let v = { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) - }; - #[cfg(any(target_os = "linux", target_os = "macos"))] - let v = { - if check_cross_page(sptr, LANES) { + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd128u::loadu(placeholder.as_ptr()) - } else { - #[cfg(any(debug_assertions, miri))] - { + } + #[cfg(any(target_os = "linux", target_os = "macos"))] + { + if check_cross_page(sptr, LANES) { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd128u::loadu(placeholder.as_ptr()) - } - #[cfg(not(any(debug_assertions, miri)))] - { - Simd128u::loadu(sptr) + } else { + #[cfg(any(debug_assertions, miri))] + { + std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); + Simd128u::loadu(placeholder.as_ptr()) + } + #[cfg(not(any(debug_assertions, miri)))] + { + Simd128u::loadu(sptr) + } } } }; diff --git a/src/simd/sse2.rs b/src/simd/sse2.rs index c433f21..11d0938 100644 --- a/src/simd/sse2.rs +++ b/src/simd/sse2.rs @@ -215,27 +215,29 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { } // Handle remaining bytes - let mut placeholder: [u8; 16] = [0; 16]; + let mut placeholder: [u8; LANES] = [0; LANES]; while nb > 0 { - #[cfg(not(any(target_os = "linux", target_os = "macos")))] let v = { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) - }; - #[cfg(any(target_os = "linux", target_os = "macos"))] - let v = { - if check_cross_page(sptr, LANES) { + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd128u::loadu(placeholder.as_ptr()) - } else { - #[cfg(any(debug_assertions, miri))] - { + } + #[cfg(any(target_os = "linux", target_os = "macos"))] + { + if check_cross_page(sptr, LANES) { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd128u::loadu(placeholder.as_ptr()) - } - #[cfg(not(any(debug_assertions, miri)))] - { - Simd128u::loadu(sptr) + } else { + #[cfg(any(debug_assertions, miri))] + { + std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); + Simd128u::loadu(placeholder.as_ptr()) + } + #[cfg(not(any(debug_assertions, miri)))] + { + Simd128u::loadu(sptr) + } } } }; @@ -247,7 +249,7 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { dptr = dptr.add(nb); break; } else { - let cn = mask.trailing_zeros() as usize; + let cn = mask.first_offset(); nb -= cn; dptr = dptr.add(cn); sptr = sptr.add(cn); diff --git a/src/simd/v128.rs b/src/simd/v128.rs index f75157f..90f48c2 100644 --- a/src/simd/v128.rs +++ b/src/simd/v128.rs @@ -1,10 +1,14 @@ use std::ops::{BitAnd, BitOr, BitOrAssign}; +use crate::simd::traits::BitMask; + use super::{Mask, Simd, util::escape_unchecked}; #[cfg(any(target_os = "linux", target_os = "macos"))] use super::util::check_cross_page; +const LANES: usize = 16; + #[derive(Debug)] pub struct Simd128u([u8; 16]); @@ -124,17 +128,17 @@ pub fn format_string(value: &str, dst: &mut [u8]) -> usize { dptr = dptr.add(1); // Main loop: process LANES bytes at a time - while nb >= Simd128u::LANES { + while nb >= LANES { let v = Simd128u::loadu(sptr); v.storeu(dptr); let mask = escaped_mask(v); if mask == 0 { - nb -= Simd128u::LANES; - dptr = dptr.add(Simd128u::LANES); - sptr = sptr.add(Simd128u::LANES); + nb -= LANES; + dptr = dptr.add(LANES); + sptr = sptr.add(LANES); } else { - let cn = mask.trailing_zeros() as usize; + let cn = mask.first_offset(); nb -= cn; dptr = dptr.add(cn); sptr = sptr.add(cn); @@ -143,27 +147,29 @@ pub fn format_string(value: &str, dst: &mut [u8]) -> usize { } // Handle remaining bytes - let mut placeholder: [u8; 16] = [0; 16]; + let mut placeholder: [u8; LANES] = [0; LANES]; while nb > 0 { - #[cfg(not(any(target_os = "linux", target_os = "macos")))] - let v = { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) - }; - #[cfg(any(target_os = "linux", target_os = "macos"))] let v = { - if check_cross_page(sptr, Simd128u::LANES) { + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd128u::loadu(placeholder.as_ptr()) - } else { - #[cfg(any(debug_assertions, miri))] - { + } + #[cfg(any(target_os = "linux", target_os = "macos"))] + { + if check_cross_page(sptr, Simd128u::LANES) { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); Simd128u::loadu(placeholder.as_ptr()) - } - #[cfg(not(any(debug_assertions, miri)))] - { - Simd128u::loadu(sptr) + } else { + #[cfg(any(debug_assertions, miri))] + { + std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); + Simd128u::loadu(placeholder.as_ptr()) + } + #[cfg(not(any(debug_assertions, miri)))] + { + Simd128u::loadu(sptr) + } } } }; @@ -177,7 +183,7 @@ pub fn format_string(value: &str, dst: &mut [u8]) -> usize { dptr = dptr.add(nb); break; } else { - let cn = mask.trailing_zeros() as usize; + let cn = mask.first_offset(); nb -= cn; dptr = dptr.add(cn); sptr = sptr.add(cn); From c3e9712cc4a1ac5be301d03a462c085cd8c430f8 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 19:23:23 +0800 Subject: [PATCH 02/10] add asan --- .github/workflows/CI.yml | 73 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8dfcac6..2734482 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -69,6 +69,79 @@ jobs: run: cargo miri test env: MIRIFLAGS: "-Zmiri-disable-isolation" + + asan: + name: ASAN - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-24.04, windows-latest] + + steps: + - uses: actions/checkout@v5 + + - name: Setup node + uses: actions/setup-node@v5 + with: + node-version: 22 + cache: 'yarn' + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: nightly + components: rust-src + + - name: Install dependencies + run: yarn install --immutable --mode=skip-build + + - name: Download fixtures + run: node download-fixtures.js + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Test with ASAN (Linux) + if: matrix.os == 'ubuntu-24.04' + run: cargo test -Zbuild-std --target x86_64-unknown-linux-gnu + env: + RUST_TARGET: x86_64-unknown-linux-gnu + RUST_BACKTRACE: 1 + RUSTFLAGS: -Z sanitizer=address + ASAN_OPTIONS: detect_leaks=1 + CARGO_UNSTABLE_BUILD_STD: std,panic_abort + + - name: Test with ASAN (Windows) + if: matrix.os == 'windows-latest' + shell: pwsh + run: | + # Set ASAN environment variables for Windows + $env:ASAN_OPTIONS = "windows_hook_rtl_allocators=true:detect_leaks=0:print_stats=1:check_initialization_order=true:strict_string_checks=true" + + # Find and set the path to the ASAN runtime DLL + $vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath + $asanDllPath = Get-ChildItem -Path "$vsPath\VC\Tools\MSVC" -Recurse -Filter "clang_rt.asan_dynamic-x86_64.dll" | Select-Object -First 1 + if ($asanDllPath) { + $env:PATH = "$($asanDllPath.DirectoryName);$env:PATH" + Write-Host "Found ASAN DLL at: $($asanDllPath.FullName)" + } + cargo test --target x86_64-pc-windows-msvc + env: + RUSTFLAGS: -Zsanitizer=address + RUSTDOCFLAGS: -Zsanitizer=address + RUST_BACKTRACE: 1 + CARGO_PROFILE_DEV_OPT_LEVEL: 1 + CARGO_UNSTABLE_BUILD_STD: std,panic_abort + + - name: Upload ASAN logs (Windows) + if: failure() && matrix.os == 'windows-latest' + uses: actions/upload-artifact@v4 + with: + name: windows-asan-logs + path: | + asan.log* + *.asan.log + bench: strategy: matrix: From 637d58a1eedb0ae347089c7a0a66a8a49a826c8c Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 20:44:43 +0800 Subject: [PATCH 03/10] more asan --- .github/workflows/CI.yml | 10 +++++----- src/simd/avx2.rs | 6 +++--- src/simd/avx512.rs | 12 ++++++------ src/simd/neon.rs | 12 ++++++------ src/simd/sse2.rs | 12 ++++++------ src/simd/v128.rs | 12 ++++++------ 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 2734482..d4df426 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -71,12 +71,13 @@ jobs: MIRIFLAGS: "-Zmiri-disable-isolation" asan: - name: ASAN - ${{ matrix.os }} + name: ASAN - ${{ matrix.os }} - ${{ matrix.asan }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-24.04, windows-latest] + asan: ['sanitizer=address', 'sanitizer=memory'] steps: - uses: actions/checkout@v5 @@ -103,12 +104,12 @@ jobs: - name: Test with ASAN (Linux) if: matrix.os == 'ubuntu-24.04' - run: cargo test -Zbuild-std --target x86_64-unknown-linux-gnu + run: cargo test --target x86_64-unknown-linux-gnu env: RUST_TARGET: x86_64-unknown-linux-gnu RUST_BACKTRACE: 1 - RUSTFLAGS: -Z sanitizer=address - ASAN_OPTIONS: detect_leaks=1 + RUSTFLAGS: "-Z ${{ matrix.asan }}" + ASAN_OPTIONS: detect_leaks=1 detect_stack_use_after_return=1 CARGO_UNSTABLE_BUILD_STD: std,panic_abort - name: Test with ASAN (Windows) @@ -128,7 +129,6 @@ jobs: cargo test --target x86_64-pc-windows-msvc env: RUSTFLAGS: -Zsanitizer=address - RUSTDOCFLAGS: -Zsanitizer=address RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_OPT_LEVEL: 1 CARGO_UNSTABLE_BUILD_STD: std,panic_abort diff --git a/src/simd/avx2.rs b/src/simd/avx2.rs index 03164aa..8d72c2e 100644 --- a/src/simd/avx2.rs +++ b/src/simd/avx2.rs @@ -224,18 +224,18 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { #[cfg(not(any(target_os = "linux", target_os = "macos")))] { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd256u::loadu(placeholder.as_ptr()) + Simd256u::loadu(placeholder[..].as_ptr()) } #[cfg(any(target_os = "linux", target_os = "macos"))] { if check_cross_page(sptr, LANES) { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd256u::loadu(placeholder.as_ptr()) + Simd256u::loadu(placeholder[..].as_ptr()) } else { #[cfg(any(debug_assertions, miri))] { std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd256u::loadu(placeholder.as_ptr()) + Simd256u::loadu(placeholder[..].as_ptr()) } #[cfg(not(any(debug_assertions, miri)))] { diff --git a/src/simd/avx512.rs b/src/simd/avx512.rs index 9aaf80b..316edd2 100644 --- a/src/simd/avx512.rs +++ b/src/simd/avx512.rs @@ -215,19 +215,19 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { let v = { #[cfg(not(any(target_os = "linux", target_os = "macos")))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd512u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd512u::loadu(placeholder[..].as_ptr()) } #[cfg(any(target_os = "linux", target_os = "macos"))] { if check_cross_page(sptr, LANES) { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd512u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd512u::loadu(placeholder[..].as_ptr()) } else { #[cfg(any(debug_assertions, miri))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd512u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd512u::loadu(placeholder[..].as_ptr()) } #[cfg(not(any(debug_assertions, miri)))] { diff --git a/src/simd/neon.rs b/src/simd/neon.rs index fce9224..0300fc1 100644 --- a/src/simd/neon.rs +++ b/src/simd/neon.rs @@ -224,19 +224,19 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { let v = { #[cfg(not(any(target_os = "linux", target_os = "macos")))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } #[cfg(any(target_os = "linux", target_os = "macos"))] { if check_cross_page(sptr, LANES) { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } else { #[cfg(any(debug_assertions, miri))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } #[cfg(not(any(debug_assertions, miri)))] { diff --git a/src/simd/sse2.rs b/src/simd/sse2.rs index 11d0938..cdcc112 100644 --- a/src/simd/sse2.rs +++ b/src/simd/sse2.rs @@ -220,19 +220,19 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { let v = { #[cfg(not(any(target_os = "linux", target_os = "macos")))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } #[cfg(any(target_os = "linux", target_os = "macos"))] { if check_cross_page(sptr, LANES) { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } else { #[cfg(any(debug_assertions, miri))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } #[cfg(not(any(debug_assertions, miri)))] { diff --git a/src/simd/v128.rs b/src/simd/v128.rs index 90f48c2..0e20392 100644 --- a/src/simd/v128.rs +++ b/src/simd/v128.rs @@ -152,19 +152,19 @@ pub fn format_string(value: &str, dst: &mut [u8]) -> usize { let v = { #[cfg(not(any(target_os = "linux", target_os = "macos")))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } #[cfg(any(target_os = "linux", target_os = "macos"))] { if check_cross_page(sptr, Simd128u::LANES) { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } else { #[cfg(any(debug_assertions, miri))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); - Simd128u::loadu(placeholder.as_ptr()) + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); + Simd128u::loadu(placeholder[..].as_ptr()) } #[cfg(not(any(debug_assertions, miri)))] { From 1763532880b69551b852a94e1ee162d7b78bd9b0 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 20:54:11 +0800 Subject: [PATCH 04/10] asan option --- .github/workflows/CI.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d4df426..4aa7576 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -71,13 +71,17 @@ jobs: MIRIFLAGS: "-Zmiri-disable-isolation" asan: - name: ASAN - ${{ matrix.os }} - ${{ matrix.asan }} + name: ASAN - ${{ matrix.os }} - ${{ matrix.asan.flag }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-24.04, windows-latest] - asan: ['sanitizer=address', 'sanitizer=memory'] + asan: + - flag: sanitizer=address + options: detect_leaks=1 detect_stack_use_after_return=1 + - flag: sanitizer=memory + options: '' steps: - uses: actions/checkout@v5 @@ -108,8 +112,8 @@ jobs: env: RUST_TARGET: x86_64-unknown-linux-gnu RUST_BACKTRACE: 1 - RUSTFLAGS: "-Z ${{ matrix.asan }}" - ASAN_OPTIONS: detect_leaks=1 detect_stack_use_after_return=1 + RUSTFLAGS: "-Z${{ matrix.asan.flag }}" + ASAN_OPTIONS: ${{ matrix.asan.options }} CARGO_UNSTABLE_BUILD_STD: std,panic_abort - name: Test with ASAN (Windows) @@ -128,7 +132,7 @@ jobs: } cargo test --target x86_64-pc-windows-msvc env: - RUSTFLAGS: -Zsanitizer=address + RUSTFLAGS: -Z${{ matrix.asan.flag }} RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_OPT_LEVEL: 1 CARGO_UNSTABLE_BUILD_STD: std,panic_abort From ba15d95b28e1b0037c667caf99d34ecdb27dfcee Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 20:55:18 +0800 Subject: [PATCH 05/10] asan option --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 4aa7576..08a95f0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -108,7 +108,7 @@ jobs: - name: Test with ASAN (Linux) if: matrix.os == 'ubuntu-24.04' - run: cargo test --target x86_64-unknown-linux-gnu + run: cargo test --tests --target x86_64-unknown-linux-gnu env: RUST_TARGET: x86_64-unknown-linux-gnu RUST_BACKTRACE: 1 @@ -130,7 +130,7 @@ jobs: $env:PATH = "$($asanDllPath.DirectoryName);$env:PATH" Write-Host "Found ASAN DLL at: $($asanDllPath.FullName)" } - cargo test --target x86_64-pc-windows-msvc + cargo test --tests --target x86_64-pc-windows-msvc env: RUSTFLAGS: -Z${{ matrix.asan.flag }} RUST_BACKTRACE: 1 From 691841018ce70170dfb7009b4b6c02cdf97b490e Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 21:10:46 +0800 Subject: [PATCH 06/10] memtag --- .github/workflows/CI.yml | 83 +++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 08a95f0..efcdc06 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -71,17 +71,21 @@ jobs: MIRIFLAGS: "-Zmiri-disable-isolation" asan: - name: ASAN - ${{ matrix.os }} - ${{ matrix.asan.flag }} - runs-on: ${{ matrix.os }} + name: ASAN - Linux-x86_64 - ${{ matrix.asan.flag }} + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: - os: [ubuntu-24.04, windows-latest] asan: - flag: sanitizer=address options: detect_leaks=1 detect_stack_use_after_return=1 + rustc_flags: '' - flag: sanitizer=memory options: '' + rustc_flags: '' + - flag: sanitizer=cfi + options: '' + rustc_flags: '-Clto' steps: - uses: actions/checkout@v5 @@ -106,18 +110,79 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Test with ASAN (Linux) - if: matrix.os == 'ubuntu-24.04' + - name: Test with ASAN run: cargo test --tests --target x86_64-unknown-linux-gnu env: RUST_TARGET: x86_64-unknown-linux-gnu RUST_BACKTRACE: 1 - RUSTFLAGS: "-Z${{ matrix.asan.flag }}" + RUSTFLAGS: "-Z${{ matrix.asan.flag }} ${{ matrix.asan.rustc_flags }}" ASAN_OPTIONS: ${{ matrix.asan.options }} CARGO_UNSTABLE_BUILD_STD: std,panic_abort + + asan-memtag: + name: ASAN memtag - Linux-arm64 + runs-on: ubuntu-24.04-arm + + steps: + - uses: actions/checkout@v5 + + - name: Setup node + uses: actions/setup-node@v5 + with: + node-version: 22 + cache: 'yarn' + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: nightly + components: rust-src + + - name: Install dependencies + run: yarn install --immutable --mode=skip-build + + - name: Download fixtures + run: node download-fixtures.js + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Test with ASAN + run: cargo test --tests --target aarch64-unknown-linux-gnu + env: + RUST_TARGET: aarch64-unknown-linux-gnu + RUST_BACKTRACE: 1 + RUSTFLAGS: -C target-feature="+mte" -Zsanitizer=memtag + CARGO_UNSTABLE_BUILD_STD: std,panic_abort + + asan-win32: + name: ASAN - Windows-x86_64 + runs-on: windows-latest + + steps: + - uses: actions/checkout@v5 + + - name: Setup node + uses: actions/setup-node@v5 + with: + node-version: 22 + cache: 'yarn' + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: nightly + components: rust-src + + - name: Install dependencies + run: yarn install --immutable --mode=skip-build + + - name: Download fixtures + run: node download-fixtures.js + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Test with ASAN (Windows) - if: matrix.os == 'windows-latest' shell: pwsh run: | # Set ASAN environment variables for Windows @@ -132,13 +197,13 @@ jobs: } cargo test --tests --target x86_64-pc-windows-msvc env: - RUSTFLAGS: -Z${{ matrix.asan.flag }} + RUSTFLAGS: -Zsanitizer=address RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_OPT_LEVEL: 1 CARGO_UNSTABLE_BUILD_STD: std,panic_abort - name: Upload ASAN logs (Windows) - if: failure() && matrix.os == 'windows-latest' + if: failure() uses: actions/upload-artifact@v4 with: name: windows-asan-logs From ef8d2944eae81e59c88c2eeffdf435afa2e41744 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 21:14:24 +0800 Subject: [PATCH 07/10] fix asan --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index efcdc06..6e6166b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -85,7 +85,7 @@ jobs: rustc_flags: '' - flag: sanitizer=cfi options: '' - rustc_flags: '-Clto' + rustc_flags: '-Clto -Ccodegen-units=1' steps: - uses: actions/checkout@v5 @@ -152,7 +152,7 @@ jobs: env: RUST_TARGET: aarch64-unknown-linux-gnu RUST_BACKTRACE: 1 - RUSTFLAGS: -C target-feature="+mte" -Zsanitizer=memtag + RUSTFLAGS: -Ctarget-feature=+mte -Zsanitizer=memtag' CARGO_UNSTABLE_BUILD_STD: std,panic_abort asan-win32: From 08127adc50c21d664338ebde7434674a7c9144f5 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 21:20:13 +0800 Subject: [PATCH 08/10] fix --- .github/workflows/CI.yml | 67 +++++++++++++--------------------------- 1 file changed, 21 insertions(+), 46 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6e6166b..93f09eb 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -35,7 +35,7 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn install - name: Download fixtures @@ -58,7 +58,7 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn install - name: Download fixtures @@ -79,13 +79,16 @@ jobs: asan: - flag: sanitizer=address options: detect_leaks=1 detect_stack_use_after_return=1 - rustc_flags: '' + rustc_flags: "" - flag: sanitizer=memory - options: '' - rustc_flags: '' + options: "" + rustc_flags: "" + - flag: sanitizer=safestack + options: "" + rustc_flags: "" - flag: sanitizer=cfi - options: '' - rustc_flags: '-Clto -Ccodegen-units=1' + options: "" + rustc_flags: "-Clto -Ccodegen-units=1 -Cembed-bitcode=yes" steps: - uses: actions/checkout@v5 @@ -94,7 +97,7 @@ jobs: uses: actions/setup-node@v5 with: node-version: 22 - cache: 'yarn' + cache: "yarn" - name: Install Rust uses: dtolnay/rust-toolchain@stable @@ -120,41 +123,6 @@ jobs: CARGO_UNSTABLE_BUILD_STD: std,panic_abort - asan-memtag: - name: ASAN memtag - Linux-arm64 - runs-on: ubuntu-24.04-arm - - steps: - - uses: actions/checkout@v5 - - - name: Setup node - uses: actions/setup-node@v5 - with: - node-version: 22 - cache: 'yarn' - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - with: - toolchain: nightly - components: rust-src - - - name: Install dependencies - run: yarn install --immutable --mode=skip-build - - - name: Download fixtures - run: node download-fixtures.js - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Test with ASAN - run: cargo test --tests --target aarch64-unknown-linux-gnu - env: - RUST_TARGET: aarch64-unknown-linux-gnu - RUST_BACKTRACE: 1 - RUSTFLAGS: -Ctarget-feature=+mte -Zsanitizer=memtag' - CARGO_UNSTABLE_BUILD_STD: std,panic_abort - asan-win32: name: ASAN - Windows-x86_64 runs-on: windows-latest @@ -166,7 +134,7 @@ jobs: uses: actions/setup-node@v5 with: node-version: 22 - cache: 'yarn' + cache: "yarn" - name: Install Rust uses: dtolnay/rust-toolchain@stable @@ -236,7 +204,7 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 - cache: 'yarn' + cache: "yarn" - name: Install dependencies run: yarn install - name: Download fixtures @@ -246,4 +214,11 @@ jobs: - name: Run benchmarks run: cargo bench env: - RUSTFLAGS: '-C target-cpu=native' \ No newline at end of file + RUSTFLAGS: "-C target-cpu=native" + + done: + runs-on: ubuntu-latest + needs: [test, miri, asan, asan-win32, bench] + steps: + - run: exit 1 + if: ${{ always() && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }} From 96d488809987cdc21b789372842066456d5c3355 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 21:22:29 +0800 Subject: [PATCH 09/10] fix --- src/simd/avx2.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/simd/avx2.rs b/src/simd/avx2.rs index 8d72c2e..c1cac44 100644 --- a/src/simd/avx2.rs +++ b/src/simd/avx2.rs @@ -223,18 +223,18 @@ pub unsafe fn format_string(value: &str, dst: &mut [u8]) -> usize { let v = { #[cfg(not(any(target_os = "linux", target_os = "macos")))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); Simd256u::loadu(placeholder[..].as_ptr()) } #[cfg(any(target_os = "linux", target_os = "macos"))] { if check_cross_page(sptr, LANES) { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); Simd256u::loadu(placeholder[..].as_ptr()) } else { #[cfg(any(debug_assertions, miri))] { - std::ptr::copy_nonoverlapping(sptr, placeholder.as_mut_ptr(), nb); + std::ptr::copy_nonoverlapping(sptr, placeholder[..].as_mut_ptr(), nb); Simd256u::loadu(placeholder[..].as_ptr()) } #[cfg(not(any(debug_assertions, miri)))] From 02d76d806515b1d6814e120e5effdb75d49ec60b Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 13 Oct 2025 21:24:18 +0800 Subject: [PATCH 10/10] remove cfi --- .github/workflows/CI.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 93f09eb..60184f7 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -79,16 +79,10 @@ jobs: asan: - flag: sanitizer=address options: detect_leaks=1 detect_stack_use_after_return=1 - rustc_flags: "" - flag: sanitizer=memory options: "" - rustc_flags: "" - flag: sanitizer=safestack options: "" - rustc_flags: "" - - flag: sanitizer=cfi - options: "" - rustc_flags: "-Clto -Ccodegen-units=1 -Cembed-bitcode=yes" steps: - uses: actions/checkout@v5 @@ -118,7 +112,7 @@ jobs: env: RUST_TARGET: x86_64-unknown-linux-gnu RUST_BACKTRACE: 1 - RUSTFLAGS: "-Z${{ matrix.asan.flag }} ${{ matrix.asan.rustc_flags }}" + RUSTFLAGS: "-Z${{ matrix.asan.flag }}" ASAN_OPTIONS: ${{ matrix.asan.options }} CARGO_UNSTABLE_BUILD_STD: std,panic_abort