From 2efa206862c05b3aaf9b2e017543bb320da883cf Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Tue, 24 Feb 2026 16:37:54 +0200 Subject: [PATCH 1/9] fix: alloc(0) call is UB --- src/lib.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5a3051ac..f449fb42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1051,6 +1051,15 @@ impl AlignedBuf { /// Creates a new buffer that is aligned with the simd register size #[must_use] pub fn with_capacity(capacity: usize) -> Self { + if capacity == 0 { + let layout = Layout::from_size_align(0, SIMDJSON_PADDING).unwrap(); + return Self { + layout, + capacity: 0, + len: 0, + inner: NonNull::dangling(), + }; + } let Ok(layout) = Layout::from_size_align(capacity, SIMDJSON_PADDING) else { Self::capacity_overflow() }; @@ -1092,8 +1101,10 @@ impl AlignedBuf { } impl Drop for AlignedBuf { fn drop(&mut self) { - unsafe { - dealloc(self.inner.as_ptr(), self.layout); + if self.capacity > 0 { + unsafe { + dealloc(self.inner.as_ptr(), self.layout); + } } } } From e07f22ed9bf53e82c721f03a5708663ad4905d85 Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Thu, 30 Apr 2026 10:48:14 +0300 Subject: [PATCH 2/9] fix clippy warnings --- src/lib.rs | 4 ++-- src/macros.rs | 2 ++ src/numberparse/approx.rs | 1 - src/numberparse/correct.rs | 1 - src/stage2.rs | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f449fb42..f7248768 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,6 @@ mod numberparse; mod safer_unchecked; mod stringparse; -use macros::static_cast_u64; use safer_unchecked::GetSaferUnchecked; use stage2::StackState; use tape::Value; @@ -1052,7 +1051,8 @@ impl AlignedBuf { #[must_use] pub fn with_capacity(capacity: usize) -> Self { if capacity == 0 { - let layout = Layout::from_size_align(0, SIMDJSON_PADDING).unwrap(); + let layout = Layout::from_size_align(0, SIMDJSON_PADDING) + .expect("Layout for size 0 should always be valid"); return Self { layout, capacity: 0, diff --git a/src/macros.rs b/src/macros.rs index 93bf572b..064e9349 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1217,6 +1217,7 @@ macro_rules! unlikely { }}; } +#[allow(unused_imports)] pub(crate) use unlikely; /// static cast to an i32 @@ -1254,6 +1255,7 @@ macro_rules! static_cast_u64 { i64::cast_unsigned($v) }; } +#[allow(unused_imports)] pub(crate) use static_cast_u64; /// Custom `try!` macro that does no `From` conversions diff --git a/src/numberparse/approx.rs b/src/numberparse/approx.rs index be283407..137e0cf9 100644 --- a/src/numberparse/approx.rs +++ b/src/numberparse/approx.rs @@ -4,7 +4,6 @@ use super::{ }; use crate::StaticNode; use crate::charutils::is_structural_or_whitespace; -use crate::macros::{static_cast_i64, unlikely}; use crate::safer_unchecked::GetSaferUnchecked; use crate::{Deserializer, ErrorType, Result}; diff --git a/src/numberparse/correct.rs b/src/numberparse/correct.rs index 381ca6d0..f5f6ee2c 100644 --- a/src/numberparse/correct.rs +++ b/src/numberparse/correct.rs @@ -9,7 +9,6 @@ use super::{is_made_of_eight_digits_fast, parse_eight_digits_unrolled}; use crate::StaticNode; use crate::charutils::is_structural_or_whitespace; use crate::error::Error; -use crate::macros::{static_cast_i64, unlikely}; use crate::safer_unchecked::GetSaferUnchecked; use crate::{Deserializer, ErrorType, Result}; diff --git a/src/stage2.rs b/src/stage2.rs index 9f4d000f..87701f90 100644 --- a/src/stage2.rs +++ b/src/stage2.rs @@ -1,6 +1,5 @@ #![allow(dead_code)] use crate::charutils::is_not_structural_or_whitespace; -use crate::macros::unlikely; use crate::safer_unchecked::GetSaferUnchecked; use crate::value::tape::Node; use crate::{Deserializer, Error, ErrorType, InternalError, Result}; From ffa238dc8e638148e4524918e7e955822bdc0e74 Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Thu, 30 Apr 2026 10:50:45 +0300 Subject: [PATCH 3/9] allow unused macro import --- src/macros.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/macros.rs b/src/macros.rs index 064e9349..07db0644 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1247,6 +1247,7 @@ macro_rules! static_cast_i64 { u64::cast_signed($v) }; } +#[allow(unused_imports)] pub(crate) use static_cast_i64; /// static cast to an u64 From 3084cb72b600967bacab69ea3e8a0ecd8301b668 Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Thu, 30 Apr 2026 10:57:06 +0300 Subject: [PATCH 4/9] install relevant wasmtime cli --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 11c013b0..e21d687c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -125,7 +125,7 @@ jobs: targets: wasm32-wasip1 - name: Install wasmtime - run: cargo install wasmtime-cli + run: cargo install wasmtime-cli --version 38.0.4 - name: Run tests run: | From 540adf506ac3e57319657131019b8491a4594cc1 Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Tue, 24 Feb 2026 16:38:54 +0200 Subject: [PATCH 5/9] fix: No UTF-8 validation happening when `portable` is disabled --- src/lib.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index f7248768..b2a59d8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -604,6 +604,27 @@ impl<'de> Deserializer<'de> { /// architecture dependant `find_structural_bits` impl Deserializer<'_> { + #[cfg_attr(not(feature = "no-inline"), inline)] + /// Native fallback that pre-validates UTF-8 before finding structural bits, + /// since the native `ChunkedUtf8ValidatorImp` is a no-op. + #[cfg(all( + feature = "runtime-detection", + any(target_arch = "x86_64", target_arch = "x86"), + not(feature = "portable"), + ))] + pub(crate) unsafe fn find_structural_bits_native( + input: &[u8], + structural_indexes: &mut Vec, + ) -> std::result::Result<(), ErrorType> { + match core::str::from_utf8(input) { + Ok(_) => (), + Err(_) => return Err(ErrorType::InvalidUtf8), + }; + unsafe { + Self::_find_structural_bits::(input, structural_indexes) + } + } + #[cfg_attr(not(feature = "no-inline"), inline)] #[cfg(all( feature = "runtime-detection", @@ -628,7 +649,7 @@ impl Deserializer<'_> { #[cfg(feature = "portable")] let r = Deserializer::_find_structural_bits::; #[cfg(not(feature = "portable"))] - let r = Deserializer::_find_structural_bits::; + let r = Deserializer::find_structural_bits_native; r } } From a20bd488f43d5279fb5ede1dcb5d68a7f9b2d9b9 Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Thu, 30 Apr 2026 11:07:45 +0300 Subject: [PATCH 6/9] ci: Enable MIRI in CI --- .github/workflows/nightly.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 6c4ef41e..43fc9d85 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -82,8 +82,7 @@ jobs: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" run: cargo test --no-default-features --features serde_impl - # we can't use miri any more, something broke. - # - name: Run miri - # env: - # RUSTFLAGS: ${{ matrix.rustflags }} - # run: cargo miri test ${{ matrix.features }} + - name: Run miri + env: + RUSTFLAGS: ${{ matrix.rustflags }} + run: cargo miri test ${{ matrix.features }} From a3920c958db9b20be8e72007c366fab150a72485 Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Thu, 30 Apr 2026 11:11:39 +0300 Subject: [PATCH 7/9] not sure where that came from --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index b2a59d8d..9156135c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -619,7 +619,7 @@ impl Deserializer<'_> { match core::str::from_utf8(input) { Ok(_) => (), Err(_) => return Err(ErrorType::InvalidUtf8), - }; + } unsafe { Self::_find_structural_bits::(input, structural_indexes) } From 111ef51d5b99d12b1388e4da9362622c0686ce5c Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Thu, 30 Apr 2026 11:15:58 +0300 Subject: [PATCH 8/9] uncomment miri install --- .github/workflows/nightly.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 43fc9d85..9933b79a 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -24,8 +24,8 @@ jobs: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly - # with: - # components: miri + with: + components: miri - name: Run tests (alloc) env: From 03f13a64eddb8bc9d41d7a1ef98f6701bb8148cc Mon Sep 17 00:00:00 2001 From: Emily Matheys Date: Thu, 30 Apr 2026 11:28:03 +0300 Subject: [PATCH 9/9] add comment and skip proptest --- .github/workflows/nightly.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 9933b79a..e5be65bb 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -85,4 +85,7 @@ jobs: - name: Run miri env: RUSTFLAGS: ${{ matrix.rustflags }} - run: cargo miri test ${{ matrix.features }} + # We can choose to run proptest tests in miri, but they are very slow, so we skip them for now. + # Can revisit this later. + # PROPTEST_CASES: "4" + run: cargo miri test ${{ matrix.features }} -- --skip prop_