tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit a87c66f07e06758428c3ce00b317c03daf79753d
parent 4ed1688c9296470b37079807762c47b90a35d0e6
Author: Erich Gubler <erichdongubler@gmail.com>
Date:   Thu,  2 Oct 2025 18:09:19 +0000

Bug 1991226 - chore(rust): upgrade `smallvec` 1.14.0 → 1.15.1 r=supply-chain-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D266740

Diffstat:
MCargo.lock | 4++--
Msupply-chain/audits.toml | 5+++++
Msupply-chain/imports.lock | 27++++++++++++++++++++-------
Mthird_party/rust/smallvec/.cargo-checksum.json | 4++--
Athird_party/rust/smallvec/Cargo.lock | 198+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mthird_party/rust/smallvec/Cargo.toml | 64+++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mthird_party/rust/smallvec/src/lib.rs | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mthird_party/rust/smallvec/src/tests.rs | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
8 files changed, 536 insertions(+), 37 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -6322,9 +6322,9 @@ checksum = "75ce4f9dc4a41b4c3476cc925f1efb11b66df373a8fde5d4b8915fa91b5d995e" [[package]] name = "smallvec" -version = "1.13.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml @@ -5669,6 +5669,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>" criteria = "safe-to-deploy" delta = "1.9.0 -> 1.10.0" +[[audits.smallvec]] +who = "Erich Gubler <erichdongubler@gmail.com>" +criteria = "safe-to-deploy" +delta = "1.14.0 -> 1.15.1" + [[audits.smart-default]] who = "Gabriele Svelto <gsvelto@mozilla.com>" criteria = "safe-to-deploy" diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock @@ -664,13 +664,6 @@ user-id = 3618 user-login = "dtolnay" user-name = "David Tolnay" -[[publisher.smallvec]] -version = "1.13.1" -when = "2024-01-19" -user-id = 2017 -user-login = "mbrubeck" -user-name = "Matt Brubeck" - [[publisher.syn]] version = "2.0.106" when = "2025-08-16" @@ -2380,6 +2373,26 @@ and there were no hits. ''' aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" +[[audits.google.audits.smallvec]] +who = "Manish Goregaokar <manishearth@google.com>" +criteria = "safe-to-deploy" +version = "1.13.2" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.smallvec]] +who = "Jonathan Hao <phao@chromium.org>" +criteria = "safe-to-deploy" +delta = "1.13.2 -> 1.14.0" +notes = """ +WARNING: This certification is a result of a **partial** audit. The +`malloc_size_of` feature has **not** been audited. This feature does +not explicitly document its safety requirements. +See also https://chromium-review.googlesource.com/c/chromium/src/+/6275133/comment/ea0d7a93_98051a2e/ +and https://github.com/servo/malloc_size_of/issues/8. +This feature is banned in gnrt_config.toml. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + [[audits.google.audits.socket2]] who = "David Koloski <dkoloski@google.com>" criteria = "safe-to-deploy" diff --git a/third_party/rust/smallvec/.cargo-checksum.json b/third_party/rust/smallvec/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"668bb964a243127d65605bb7a0d8d3c81bcbd8f7656a5b5734766ef534b4abcb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"d82015eae942ee5cf74ace8c3c260ee2c6b5bcbeeb87254d2c72622c747a708a","debug_metadata/README.md":"4d7f1c1b2c25ce2231ef71864d06e54323867459035b53bc9e00f66a0a44f82e","debug_metadata/smallvec.natvis":"3092ddebd8fffc3486536d7f27f8c5eae3a8a093d45cd8eeb3946ea2b0c35a15","scripts/run_miri.sh":"74a9f9adc43f986e81977b03846f7dd00122a0150bd8ec3fe4842a1a787e0f07","src/arbitrary.rs":"22e55cfbf60374945b30e6d0855129eff67cd8b878cef6fa997e1f4be67b9e3d","src/lib.rs":"25fe85b6ae7b3972211bf57aeded4c7b72c47e4d843c7a4ba66908442197b5a0","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"29c6e5dad62ebfea74e5116ac4a344b127b91cfb769fe9ba8b02b53773cf7ec8","tests/debugger_visualizer.rs":"185456ad253957fc0c9e904ff8a1135397ac991c29fa3c60f75d8d81f7463022","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"} -\ No newline at end of file +{"files":{"Cargo.lock":"bc6c5ff08e0ba6534eb5490aca5b2c7a0b09b141127f8405734c1aa975cb8a25","Cargo.toml":"23b775d343d15c7c212134c69a791d75fcdfb4527224b20daf401b494dd4f0c9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"d82015eae942ee5cf74ace8c3c260ee2c6b5bcbeeb87254d2c72622c747a708a","debug_metadata/README.md":"4d7f1c1b2c25ce2231ef71864d06e54323867459035b53bc9e00f66a0a44f82e","debug_metadata/smallvec.natvis":"3092ddebd8fffc3486536d7f27f8c5eae3a8a093d45cd8eeb3946ea2b0c35a15","scripts/run_miri.sh":"74a9f9adc43f986e81977b03846f7dd00122a0150bd8ec3fe4842a1a787e0f07","src/arbitrary.rs":"22e55cfbf60374945b30e6d0855129eff67cd8b878cef6fa997e1f4be67b9e3d","src/lib.rs":"881e5b2c9afecd0091df0d1232fd557edbb9d58304d073356b066728af14ab2e","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"77d7dac593a3d4228b99de547fb81de8c451da5fe4f409c48670c6d463ef6f49","tests/debugger_visualizer.rs":"185456ad253957fc0c9e904ff8a1135397ac991c29fa3c60f75d8d81f7463022","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"} +\ No newline at end of file diff --git a/third_party/rust/smallvec/Cargo.lock b/third_party/rust/smallvec/Cargo.lock @@ -0,0 +1,198 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "unty", +] + +[[package]] +name = "debugger_test" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95bb55f592fbb86947bee426d831de84bd65602a54f5cdcb10bfa70a62e52a0" +dependencies = [ + "anyhow", + "log", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "debugger_test_parser" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe536452a777752b9316f0c840afbb94a2411684d4f15c081449ea801ef9e75" +dependencies = [ + "anyhow", + "log", + "regex", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "malloc_size_of" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d719de8b8f230028cf8192ae4c1b25267cd6b8a99d2747d345a70b8c81aa13" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +dependencies = [ + "arbitrary", + "bincode 1.3.3", + "bincode 2.0.1", + "debugger_test", + "debugger_test_parser", + "malloc_size_of", + "serde", + "unty", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" diff --git a/third_party/rust/smallvec/Cargo.toml b/third_party/rust/smallvec/Cargo.toml @@ -12,8 +12,14 @@ [package] edition = "2018" name = "smallvec" -version = "1.13.1" +version = "1.15.1" authors = ["The Servo Project Developers"] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false description = "'Small vector' optimization: store up to a small number of items on the stack" documentation = "https://docs.rs/smallvec/" readme = "README.md" @@ -36,37 +42,69 @@ rustdoc-args = [ "--generate-link-to-definition", ] +[features] +const_generics = [] +const_new = ["const_generics"] +debugger_visualizer = [] +drain_filter = [] +drain_keep_rest = ["drain_filter"] +impl_bincode = [ + "bincode", + "unty", +] +may_dangle = [] +specialization = [] +union = [] +write = [] + +[lib] +name = "smallvec" +path = "src/lib.rs" + [[test]] name = "debugger_visualizer" path = "tests/debugger_visualizer.rs" test = false required-features = ["debugger_visualizer"] +[[test]] +name = "macro" +path = "tests/macro.rs" + +[[bench]] +name = "bench" +path = "benches/bench.rs" + [dependencies.arbitrary] version = "1" optional = true +[dependencies.bincode] +version = "2" +optional = true +default-features = false + +[dependencies.malloc_size_of] +version = "0.1" +optional = true +default-features = false + [dependencies.serde] version = "1" optional = true default-features = false -[dev-dependencies.bincode] +[dependencies.unty] +version = "0.0.4" +optional = true +default-features = false + +[dev-dependencies.bincode1] version = "1.0.1" +package = "bincode" [dev-dependencies.debugger_test] version = "0.1.0" [dev-dependencies.debugger_test_parser] version = "0.1.0" - -[features] -const_generics = [] -const_new = ["const_generics"] -debugger_visualizer = [] -drain_filter = [] -drain_keep_rest = ["drain_filter"] -may_dangle = [] -specialization = [] -union = [] -write = [] diff --git a/third_party/rust/smallvec/src/lib.rs b/third_party/rust/smallvec/src/lib.rs @@ -126,6 +126,9 @@ use core::ops::{self, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; +#[cfg(feature = "malloc_size_of")] +use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps}; + #[cfg(feature = "serde")] use serde::{ de::{Deserialize, Deserializer, SeqAccess, Visitor}, @@ -177,23 +180,24 @@ use core::mem::ManuallyDrop; /// example, `smallvec![Rc::new(1); 5]` will create a vector of five references /// to the same boxed integer value, not five references pointing to independently /// boxed integers. - #[macro_export] macro_rules! smallvec { // count helper: transform any expression into 1 (@one $x:expr) => (1usize); + () => ( + $crate::SmallVec::new() + ); ($elem:expr; $n:expr) => ({ $crate::SmallVec::from_elem($elem, $n) }); - ($($x:expr),*$(,)*) => ({ - let count = 0usize $(+ $crate::smallvec!(@one $x))*; - #[allow(unused_mut)] + ($($x:expr),+$(,)?) => ({ + let count = 0usize $(+ $crate::smallvec!(@one $x))+; let mut vec = $crate::SmallVec::new(); if count <= vec.inline_size() { $(vec.push($x);)* vec } else { - $crate::SmallVec::from_vec($crate::alloc::vec![$($x,)*]) + $crate::SmallVec::from_vec($crate::alloc::vec![$($x,)+]) } }); } @@ -1372,13 +1376,14 @@ impl<A: Array> SmallVec<A> { } let mut ptr = ptr.as_ptr(); let len = *len_ptr; + if index > len { + panic!("index exceeds length"); + } + // SAFETY: add is UB if index > len, but we panicked first ptr = ptr.add(index); if index < len { + // Shift element to the right of `index`. ptr::copy(ptr, ptr.add(1), len - index); - } else if index == len { - // No elements need shifting. - } else { - panic!("index exceeds length"); } *len_ptr = len + 1; ptr::write(ptr, element); @@ -1532,7 +1537,7 @@ impl<A: Array> SmallVec<A> { /// Retains only the elements specified by the predicate. /// /// This method is identical in behaviour to [`retain`]; it is included only - /// to maintain api-compatability with `std::Vec`, where the methods are + /// to maintain api-compatibility with `std::Vec`, where the methods are /// separate for historical reasons. pub fn retain_mut<F: FnMut(&mut A::Item) -> bool>(&mut self, f: F) { self.retain(f) @@ -1970,6 +1975,32 @@ where } } +#[cfg(feature = "malloc_size_of")] +impl<A: Array> MallocShallowSizeOf for SmallVec<A> { + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if self.spilled() { + unsafe { ops.malloc_size_of(self.as_ptr()) } + } else { + 0 + } + } +} + +#[cfg(feature = "malloc_size_of")] +impl<A> MallocSizeOf for SmallVec<A> +where + A: Array, + A::Item: MallocSizeOf, +{ + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + let mut n = self.shallow_size_of(ops); + for elem in self.iter() { + n += elem.size_of(ops); + } + n + } +} + #[cfg(feature = "specialization")] trait SpecFrom<A: Array, S> { fn spec_from(slice: S) -> SmallVec<A>; @@ -2469,3 +2500,106 @@ impl<T> Clone for ConstNonNull<T> { } impl<T> Copy for ConstNonNull<T> {} + +#[cfg(feature = "impl_bincode")] +use bincode::{ + de::{BorrowDecoder, Decode, Decoder, read::Reader}, + enc::{Encode, Encoder, write::Writer}, + error::{DecodeError, EncodeError}, + BorrowDecode, +}; + +#[cfg(feature = "impl_bincode")] +impl<A, Context> Decode<Context> for SmallVec<A> +where + A: Array, + A::Item: Decode<Context>, +{ + fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> { + use core::convert::TryInto; + let len = u64::decode(decoder)?; + let len = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?; + decoder.claim_container_read::<A::Item>(len)?; + + let mut vec = SmallVec::with_capacity(len); + if unty::type_equal::<A::Item, u8>() { + // Initialize the smallvec's buffer. Note that we need to do this through + // the raw pointer as we cannot name the type [u8; N] even though A::Item is u8. + let ptr = vec.as_mut_ptr(); + // SAFETY: A::Item is u8 and the smallvec has been allocated with enough capacity + unsafe { + core::ptr::write_bytes(ptr, 0, len); + vec.set_len(len); + } + // Read the data into the smallvec's buffer. + let slice = vec.as_mut_slice(); + // SAFETY: A::Item is u8 + let slice = unsafe { core::mem::transmute::<&mut [A::Item], &mut [u8]>(slice) }; + decoder.reader().read(slice)?; + } else { + for _ in 0..len { + decoder.unclaim_bytes_read(core::mem::size_of::<A::Item>()); + vec.push(A::Item::decode(decoder)?); + } + } + Ok(vec) + } +} + +#[cfg(feature = "impl_bincode")] +impl<'de, A, Context> BorrowDecode<'de, Context> for SmallVec<A> +where + A: Array, + A::Item: BorrowDecode<'de, Context>, +{ + fn borrow_decode<D: BorrowDecoder<'de, Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> { + use core::convert::TryInto; + let len = u64::decode(decoder)?; + let len = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?; + decoder.claim_container_read::<A::Item>(len)?; + + let mut vec = SmallVec::with_capacity(len); + if unty::type_equal::<A::Item, u8>() { + // Initialize the smallvec's buffer. Note that we need to do this through + // the raw pointer as we cannot name the type [u8; N] even though A::Item is u8. + let ptr = vec.as_mut_ptr(); + // SAFETY: A::Item is u8 and the smallvec has been allocated with enough capacity + unsafe { + core::ptr::write_bytes(ptr, 0, len); + vec.set_len(len); + } + // Read the data into the smallvec's buffer. + let slice = vec.as_mut_slice(); + // SAFETY: A::Item is u8 + let slice = unsafe { core::mem::transmute::<&mut [A::Item], &mut [u8]>(slice) }; + decoder.reader().read(slice)?; + } else { + for _ in 0..len { + decoder.unclaim_bytes_read(core::mem::size_of::<A::Item>()); + vec.push(A::Item::borrow_decode(decoder)?); + } + } + Ok(vec) + } +} + +#[cfg(feature = "impl_bincode")] +impl<A> Encode for SmallVec<A> +where + A: Array, + A::Item: Encode, +{ + fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> { + (self.len() as u64).encode(encoder)?; + if unty::type_equal::<A::Item, u8>() { + // Safety: A::Item is u8 + let slice: &[u8] = unsafe { core::mem::transmute(self.as_slice()) }; + encoder.writer().write(slice)?; + } else { + for item in self.iter() { + item.encode(encoder)?; + } + } + Ok(()) + } +} diff --git a/third_party/rust/smallvec/src/tests.rs b/third_party/rust/smallvec/src/tests.rs @@ -752,7 +752,7 @@ fn test_from_vec() { #[test] fn test_retain() { - // Test inline data storate + // Test inline data storage let mut sv: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]); sv.retain(|&mut i| i != 3); assert_eq!(sv.pop(), Some(4)); @@ -835,7 +835,7 @@ fn test_write() { #[cfg(feature = "serde")] #[test] fn test_serde() { - use bincode::{config, deserialize}; + use bincode1::{config, deserialize}; let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new(); small_vec.push(1); let encoded = config().limit(100).serialize(&small_vec).unwrap(); @@ -996,7 +996,23 @@ fn test_clone_from() { #[test] fn test_size() { use core::mem::size_of; - assert_eq!(24, size_of::<SmallVec<[u8; 8]>>()); + const PTR_SIZE: usize = size_of::<usize>(); + #[cfg(feature = "union")] + { + assert_eq!(3 * PTR_SIZE, size_of::<SmallVec<[u8; 0]>>()); + assert_eq!(3 * PTR_SIZE, size_of::<SmallVec<[u8; 1]>>()); + assert_eq!(3 * PTR_SIZE, size_of::<SmallVec<[u8; PTR_SIZE]>>()); + assert_eq!(3 * PTR_SIZE, size_of::<SmallVec<[u8; PTR_SIZE + 1]>>()); + assert_eq!(3 * PTR_SIZE, size_of::<SmallVec<[u8; 2 * PTR_SIZE]>>()); + assert_eq!(4 * PTR_SIZE, size_of::<SmallVec<[u8; 2 * PTR_SIZE + 1]>>()); + } + #[cfg(not(feature = "union"))] + { + assert_eq!(3 * PTR_SIZE, size_of::<SmallVec<[u8; 0]>>()); + assert_eq!(3 * PTR_SIZE, size_of::<SmallVec<[u8; 1]>>()); + assert_eq!(3 * PTR_SIZE, size_of::<SmallVec<[u8; PTR_SIZE]>>()); + assert_eq!(4 * PTR_SIZE, size_of::<SmallVec<[u8; PTR_SIZE + 1]>>()); + } } #[cfg(feature = "drain_filter")] @@ -1023,3 +1039,98 @@ fn drain_keep_rest() { assert_eq!(a, SmallVec::<[i32; 3]>::from_slice(&[1i32, 3, 5, 6, 7, 8])); } + +/// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments +/// given to SmallVec. Draining and extending the allocation are fairly well-tested earlier, but +/// `smallvec.insert(usize::MAX, val)` once slipped by! +/// +/// All code that indexes into SmallVecs should be tested with such "trivially wrong" args. +#[test] +fn max_dont_panic() { + let mut sv: SmallVec<[i32; 2]> = smallvec![0]; + let _ = sv.get(usize::MAX); + sv.truncate(usize::MAX); +} + +#[test] +#[should_panic] +fn max_remove() { + let mut sv: SmallVec<[i32; 2]> = smallvec![0]; + sv.remove(usize::MAX); +} + +#[test] +#[should_panic] +fn max_swap_remove() { + let mut sv: SmallVec<[i32; 2]> = smallvec![0]; + sv.swap_remove(usize::MAX); +} + +#[test] +#[should_panic] +fn test_insert_out_of_bounds() { + let mut v: SmallVec<[i32; 4]> = SmallVec::new(); + v.insert(10, 6); +} + +#[cfg(feature = "impl_bincode")] +#[test] +fn test_bincode() { + let config = bincode::config::standard(); + let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new(); + let mut buffer = [0u8; 128]; + small_vec.push(1); + let bytes_written = bincode::encode_into_slice(&small_vec, &mut buffer, config).unwrap(); + let (decoded, bytes_read) = + bincode::decode_from_slice::<SmallVec<[i32; 2]>, _>(&buffer, config).unwrap(); + assert_eq!(bytes_written, bytes_read); + assert_eq!(small_vec, decoded); + let (decoded, bytes_read) = + bincode::borrow_decode_from_slice::<SmallVec<[i32; 2]>, _>(&buffer, config).unwrap(); + assert_eq!(bytes_written, bytes_read); + assert_eq!(small_vec, decoded); + // Spill the vec + small_vec.push(2); + small_vec.push(3); + small_vec.push(4); + // Check again after spilling. + let bytes_written = bincode::encode_into_slice(&small_vec, &mut buffer, config).unwrap(); + let (decoded, bytes_read) = + bincode::decode_from_slice::<SmallVec<[i32; 2]>, _>(&buffer, config).unwrap(); + assert_eq!(bytes_written, bytes_read); + assert_eq!(small_vec, decoded); + let (decoded, bytes_read) = + bincode::borrow_decode_from_slice::<SmallVec<[i32; 2]>, _>(&buffer, config).unwrap(); + assert_eq!(bytes_written, bytes_read); + assert_eq!(small_vec, decoded); +} + +#[cfg(feature = "impl_bincode")] +#[test] +fn test_bincode_u8() { + let config = bincode::config::standard(); + let mut small_vec: SmallVec<[u8; 16]> = SmallVec::new(); + let mut buffer = [0u8; 128]; + small_vec.extend_from_slice(b"testing test"); + let bytes_written = bincode::encode_into_slice(&small_vec, &mut buffer, config).unwrap(); + let (decoded, bytes_read) = + bincode::decode_from_slice::<SmallVec<[u8; 16]>, _>(&buffer, config).unwrap(); + assert_eq!(bytes_written, bytes_read); + assert_eq!(small_vec, decoded); + let (decoded, bytes_read) = + bincode::borrow_decode_from_slice::<SmallVec<[u8; 16]>, _>(&buffer, config).unwrap(); + assert_eq!(bytes_written, bytes_read); + assert_eq!(small_vec, decoded); + // Spill the vec + small_vec.extend_from_slice(b"some more testing"); + // Check again after spilling. + let bytes_written = bincode::encode_into_slice(&small_vec, &mut buffer, config).unwrap(); + let (decoded, bytes_read) = + bincode::decode_from_slice::<SmallVec<[u8; 16]>, _>(&buffer, config).unwrap(); + assert_eq!(bytes_written, bytes_read); + assert_eq!(small_vec, decoded); + let (decoded, bytes_read) = + bincode::borrow_decode_from_slice::<SmallVec<[u8; 16]>, _>(&buffer, config).unwrap(); + assert_eq!(bytes_written, bytes_read); + assert_eq!(small_vec, decoded); +}