diff --git a/.github/workflows/Miri.yml b/.github/workflows/Miri.yml new file mode 100644 index 00000000..f4ef3dc3 --- /dev/null +++ b/.github/workflows/Miri.yml @@ -0,0 +1,19 @@ +name: Miri + +on: [workflow_dispatch] +jobs: + Miri: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: nightly + - run: cargo check + - run: cargo build + - run: rustup component add --toolchain nightly miri + # Test with all features: this won't test the non-compact code paths however + - run: cargo miri test --all-features + - run: cargo miri test --features radix,format,write-integers,write-floats,parse-integers,parse-floats diff --git a/CHANGELOG b/CHANGELOG index 5fab5d8e..139a5a03 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,11 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Added fuzzing and miri code safety analysis to our CI pipelines. +- Removed requirement of `alloc` in `no_std` ennvironments without the `write` feature. + ### Changed - Updated the MSRV to 1.63.0 (1.65.0 for development). - Improved performance due to compiler regressions in rustc 1.81.0 and above. +### Fixed + +- Removed use of undefined behavior in `MaybeUninit`. +- Provide better safety documentation. +- Parsing of Ruby float literals. +- Performance regressions in Rust 1.81.0+. +- Removed incorrect bounds checking in reading from iterators. +- Overflow checking with integer parsing. +- Writing `-0.0` with a leading `-`. + ### Removed - Support for mips (MIPS), mipsel (MIPS LE), mips64 (MIPS64 BE), and mips64el (MIPS64 LE) on Linux. diff --git a/lexical-write-float/src/compact.rs b/lexical-write-float/src/compact.rs index b3e99d1d..759effe4 100644 --- a/lexical-write-float/src/compact.rs +++ b/lexical-write-float/src/compact.rs @@ -25,7 +25,6 @@ use crate::float::{ExtendedFloat80, RawFloat}; use crate::options::Options; use crate::shared; use crate::table::GRISU_POWERS_OF_TEN; -use core::mem; use lexical_util::algorithm::rtrim_char_count; #[cfg(feature = "f16")] use lexical_util::bf16::bf16; @@ -64,9 +63,7 @@ pub unsafe fn write_float( debug_assert!(float >= F::ZERO); // Write our mantissa digits to a temporary buffer. - let digits: mem::MaybeUninit<[u8; 32]> = mem::MaybeUninit::uninit(); - // SAFETY: safe, since we never read bytes that weren't written. - let mut digits = unsafe { digits.assume_init() }; + let mut digits: [u8; 32] = [0u8; 32]; let (digit_count, kappa, carried) = if float == F::ZERO { // SAFETY: safe since `digits.len() == 32`. unsafe { index_unchecked_mut!(digits[0]) = b'0' }; diff --git a/lexical-write-float/src/radix.rs b/lexical-write-float/src/radix.rs index dc9cc7da..56e9c7eb 100644 --- a/lexical-write-float/src/radix.rs +++ b/lexical-write-float/src/radix.rs @@ -14,7 +14,6 @@ use crate::options::{Options, RoundMode}; use crate::shared; -use core::mem; use lexical_util::algorithm::{ltrim_char_count, rtrim_char_count}; use lexical_util::constants::{FormattedSize, BUFFER_SIZE}; use lexical_util::digit::{char_to_digit_const, digit_to_char_const}; @@ -67,10 +66,7 @@ where // either way, with additional space for sign, decimal point and string // termination should be sufficient. const SIZE: usize = 2200; - let buffer: mem::MaybeUninit<[u8; SIZE]> = mem::MaybeUninit::uninit(); - // SAFETY: safe, since we never read bytes that weren't written. - let mut buffer = unsafe { buffer.assume_init() }; - //let buffer = buffer.as_mut_ptr(); + let mut buffer = [0u8; SIZE]; let initial_cursor: usize = SIZE / 2; let mut integer_cursor = initial_cursor; let mut fraction_cursor = initial_cursor;