diff options
author | Alice Ryhl <aliceryhl@google.com> | 2023-10-24 14:58:03 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-10-24 14:58:03 +0000 |
commit | fa5d7d3c3990f9002707e072fc87550ca868c85a (patch) | |
tree | d4f09d781d9cddc8da2e810e614f5aeb8947bf09 | |
parent | af5a95a9d2962d34d17767649bf1b9b018afdefc (diff) | |
parent | 88740a120673cb4c7af8295116f398b9536f0f10 (diff) | |
download | ahash-fa5d7d3c3990f9002707e072fc87550ca868c85a.tar.gz |
Upgrade ahash to 0.8.5 am: 88740a1206
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/ahash/+/2801334
Change-Id: I80c202f26f50902e31f1695a409ac22f5ec5d851
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | .github/workflows/rust.yml | 15 | ||||
-rw-r--r-- | Android.bp | 5 | ||||
-rw-r--r-- | Cargo.toml | 13 | ||||
-rw-r--r-- | Cargo.toml.orig | 3 | ||||
-rw-r--r-- | METADATA | 10 | ||||
-rw-r--r-- | src/aes_hash.rs | 13 | ||||
-rw-r--r-- | src/convert.rs | 7 | ||||
-rw-r--r-- | src/hash_quality_test.rs | 44 | ||||
-rw-r--r-- | src/operations.rs | 35 |
10 files changed, 94 insertions, 53 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 5f20ebf..a2a6019 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "f9acd508bd89e7c5b2877a9510098100f9018d64" + "sha1": "7bbbd833cb48c6f8e64bd94c196a700c09bb97e4" }, "path_in_vcs": "" }
\ No newline at end of file diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c551724..f09853c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -51,7 +51,7 @@ jobs: env: RUSTFLAGS: -C target-cpu=native steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - name: Install latest nightly uses: actions-rs/toolchain@v1 with: @@ -89,6 +89,19 @@ jobs: with: command: check args: --target armv7-unknown-linux-gnueabihf + aarch64-apple-darwin: + name: Aarch64 Apple Darwin + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: aarch64-apple-darwin + - uses: actions-rs/cargo@v1 + with: + command: check + args: --target aarch64-apple-darwin i686-unknown-linux-gnu: name: Linux i686 runs-on: ubuntu-latest @@ -42,7 +42,7 @@ rust_library { host_supported: true, crate_name: "ahash", cargo_env_compat: true, - cargo_pkg_version: "0.8.3", + cargo_pkg_version: "0.8.5", srcs: ["src/lib.rs"], edition: "2018", arch: { @@ -57,14 +57,13 @@ rust_library { "default", "getrandom", "runtime-rng", - "specialize", "std", - "stdsimd", ], rustlibs: [ "libcfg_if", "libgetrandom", "libonce_cell", + "libzerocopy", ], apex_available: [ "//apex_available:platform", @@ -12,7 +12,7 @@ [package] edition = "2018" name = "ahash" -version = "0.8.3" +version = "0.8.5" authors = ["Tom Kaitchuck <Tom.Kaitchuck@gmail.com>"] build = "./build.rs" exclude = [ @@ -38,6 +38,7 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/tkaitchuck/ahash" [package.metadata.docs.rs] +features = ["std"] rustc-args = [ "-C", "target-feature=+aes", @@ -46,20 +47,19 @@ rustdoc-args = [ "-C", "target-feature=+aes", ] -features = ["std"] [profile.bench] opt-level = 3 lto = "fat" codegen-units = 1 -debug = false +debug = 0 debug-assertions = false [profile.release] opt-level = 3 lto = "fat" codegen-units = 1 -debug = false +debug = 0 debug-assertions = false [profile.test] @@ -103,6 +103,11 @@ optional = true version = "1.0.117" optional = true +[dependencies.zerocopy] +version = "0.7.0" +features = ["simd"] +default-features = false + [dev-dependencies.criterion] version = "0.3.2" features = ["html_reports"] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 9b19105..b340522 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "ahash" -version = "0.8.3" +version = "0.8.5" authors = ["Tom Kaitchuck <Tom.Kaitchuck@gmail.com>"] license = "MIT OR Apache-2.0" description = "A non-cryptographic hash function using AES-NI for high performance" @@ -80,6 +80,7 @@ serde = { version = "1.0.117", optional = true } cfg-if = "1.0" atomic-polyfill = { version="1.0.1", optional=true} getrandom = { version = "0.2.7", optional = true } +zerocopy = { version = "0.7.0", default-features = false, features = ["simd"] } [target.'cfg(not(all(target_arch = "arm", target_os = "none")))'.dependencies] once_cell = { version = "1.13.1", default-features = false, features = ["unstable", "alloc"] } @@ -1,6 +1,6 @@ # This project was upgraded with external_updater. # Usage: tools/external_updater/updater.sh update rust/crates/ahash -# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md +# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md name: "ahash" description: "A non-cryptographic hash function using AES-NI for high performance" @@ -11,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/ahash/ahash-0.8.3.crate" + value: "https://static.crates.io/crates/ahash/ahash-0.8.5.crate" } - version: "0.8.3" + version: "0.8.5" license_type: NOTICE last_upgrade_date { year: 2023 - month: 2 - day: 15 + month: 10 + day: 24 } } diff --git a/src/aes_hash.rs b/src/aes_hash.rs index 702044e..d3b673f 100644 --- a/src/aes_hash.rs +++ b/src/aes_hash.rs @@ -164,10 +164,10 @@ impl Hasher for AHasher { let tail = data.read_last_u128x4(); let mut current: [u128; 4] = [self.key; 4]; current[0] = aesenc(current[0], tail[0]); - current[1] = aesenc(current[1], tail[1]); + current[1] = aesdec(current[1], tail[1]); current[2] = aesenc(current[2], tail[2]); - current[3] = aesenc(current[3], tail[3]); - let mut sum: [u128; 2] = [self.key, self.key]; + current[3] = aesdec(current[3], tail[3]); + let mut sum: [u128; 2] = [self.key, !self.key]; sum[0] = add_by_64s(sum[0].convert(), tail[0].convert()).convert(); sum[1] = add_by_64s(sum[1].convert(), tail[1].convert()).convert(); sum[0] = shuffle_and_add(sum[0], tail[2]); @@ -184,8 +184,9 @@ impl Hasher for AHasher { sum[1] = shuffle_and_add(sum[1], blocks[3]); data = rest; } - self.hash_in_2(aesenc(current[0], current[1]), aesenc(current[2], current[3])); - self.hash_in(add_by_64s(sum[0].convert(), sum[1].convert()).convert()); + self.hash_in_2(current[0], current[1]); + self.hash_in_2(current[2], current[3]); + self.hash_in_2(sum[0], sum[1]); } else { //len 33-64 let (head, _) = data.read_u128x2(); @@ -209,7 +210,7 @@ impl Hasher for AHasher { fn finish(&self) -> u64 { let combined = aesdec(self.sum, self.enc); let result: [u64; 2] = aesenc(aesenc(combined, self.key), combined).convert(); - result[0] + result[1] } } diff --git a/src/convert.rs b/src/convert.rs index fc47baa..712eae1 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -7,13 +7,13 @@ macro_rules! convert { impl Convert<$b> for $a { #[inline(always)] fn convert(self) -> $b { - unsafe { core::mem::transmute::<$a, $b>(self) } + zerocopy::transmute!(self) } } impl Convert<$a> for $b { #[inline(always)] fn convert(self) -> $a { - unsafe { core::mem::transmute::<$b, $a>(self) } + zerocopy::transmute!(self) } } }; @@ -65,8 +65,7 @@ macro_rules! as_array { { #[inline(always)] fn as_array<T>(slice: &[T]) -> &[T; $len] { - assert_eq!(slice.len(), $len); - unsafe { &*(slice.as_ptr() as *const [_; $len]) } + core::convert::TryFrom::try_from(slice).unwrap() } as_array($input) } diff --git a/src/hash_quality_test.rs b/src/hash_quality_test.rs index 8f13d24..25356e4 100644 --- a/src/hash_quality_test.rs +++ b/src/hash_quality_test.rs @@ -1,5 +1,5 @@ use core::hash::{Hash, Hasher}; -use std::collections::HashMap; +use std::collections::{HashMap}; fn assert_sufficiently_different(a: u64, b: u64, tolerance: i32) { let (same_byte_count, same_nibble_count) = count_same_bytes_and_nibbles(a, b); @@ -71,12 +71,8 @@ fn test_no_full_collisions<T: Hasher>(gen_hash: impl Fn() -> T) { gen_combinations(&options, 7, Vec::new(), &mut combinations); let mut map: HashMap<u64, Vec<u8>> = HashMap::new(); for combination in combinations { - let array = unsafe { - let (begin, middle, end) = combination.align_to::<u8>(); - assert_eq!(0, begin.len()); - assert_eq!(0, end.len()); - middle.to_vec() - }; + use zerocopy::AsBytes; + let array = combination.as_slice().as_bytes().to_vec(); let mut hasher = gen_hash(); hasher.write(&array); let hash = hasher.finish(); @@ -342,6 +338,28 @@ fn test_length_extension<T: Hasher>(hasher: impl Fn(u128, u128) -> T) { } } +fn test_sparse<T: Hasher>(hasher: impl Fn() -> T) { + let mut buf = [0u8; 256]; + let mut hashes = HashMap::new(); + for idx_1 in 0..256 { + for idx_2 in idx_1+1..256 { + for value_1 in [1, 2, 4, 8, 16, 32, 64, 128] { + for value_2 in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 16, 17, 18, 20, 24, 31, 32, 33, 48, 64, 96, 127, 128, 129, 192, 254, 255] { + buf[idx_1] = value_1; + buf[idx_2] = value_2; + let hash_value = hash_with(&buf, &mut hasher()); + let keys = hashes.entry(hash_value).or_insert(Vec::new()); + keys.push((idx_1, value_1, idx_2, value_2)); + buf[idx_1] = 0; + buf[idx_2] = 0; + } + } + } + } + hashes.retain(|_key, value| value.len() != 1); + assert_eq!(0, hashes.len(), "Collision with: {:?}", hashes); +} + #[cfg(test)] mod fallback_tests { use crate::fallback_hash::*; @@ -408,6 +426,12 @@ mod fallback_tests { fn fallback_length_extension() { test_length_extension(|a, b| AHasher::new_with_keys(a, b)); } + + #[test] + fn test_no_sparse_collisions() { + test_sparse(|| AHasher::new_with_keys(0, 0)); + test_sparse(|| AHasher::new_with_keys(1, 2)); + } } ///Basic sanity tests of the cypto properties of aHash. @@ -501,4 +525,10 @@ mod aes_tests { fn aes_length_extension() { test_length_extension(|a, b| AHasher::test_with_keys(a, b)); } + + #[test] + fn aes_no_sparse_collisions() { + test_sparse(|| AHasher::test_with_keys(0, 0)); + test_sparse(|| AHasher::test_with_keys(1, 2)); + } } diff --git a/src/operations.rs b/src/operations.rs index ffd3b1a..23d4e22 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -1,4 +1,5 @@ use crate::convert::*; +use zerocopy::transmute; ///This constant comes from Kunth's prng (Empirically it works better than those from splitmix32). pub(crate) const MULTIPLE: u64 = 6364136223846793005; @@ -55,8 +56,7 @@ pub(crate) fn shuffle(a: u128) -> u128 { use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; - use core::mem::transmute; - unsafe { transmute(_mm_shuffle_epi8(transmute(a), transmute(SHUFFLE_MASK))) } + unsafe { transmute!(_mm_shuffle_epi8(transmute!(a), transmute!(SHUFFLE_MASK))) } } #[cfg(not(all(target_feature = "ssse3", not(miri))))] { @@ -81,13 +81,12 @@ pub(crate) fn shuffle_and_add(base: u128, to_add: u128) -> u128 { #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2", not(miri)))] #[inline(always)] pub(crate) fn add_by_64s(a: [u64; 2], b: [u64; 2]) -> [u64; 2] { - use core::mem::transmute; unsafe { #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; - transmute(_mm_add_epi64(transmute(a), transmute(b))) + transmute!(_mm_add_epi64(transmute!(a), transmute!(b))) } } @@ -105,10 +104,9 @@ pub(crate) fn aesenc(value: u128, xor: u128) -> u128 { use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; - use core::mem::transmute; unsafe { - let value = transmute(value); - transmute(_mm_aesenc_si128(value, transmute(xor))) + let value = transmute!(value); + transmute!(_mm_aesenc_si128(value, transmute!(xor))) } } @@ -125,11 +123,9 @@ pub(crate) fn aesenc(value: u128, xor: u128) -> u128 { use core::arch::aarch64::*; #[cfg(target_arch = "arm")] use core::arch::arm::*; - use core::mem::transmute; - unsafe { - let value = transmute(value); - transmute(vaesmcq_u8(vaeseq_u8(value, transmute(xor)))) - } + let res = unsafe { vaesmcq_u8(vaeseq_u8(transmute!(value), transmute!(0u128))) }; + let value: u128 = transmute!(res); + xor ^ value } #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))] @@ -140,10 +136,9 @@ pub(crate) fn aesdec(value: u128, xor: u128) -> u128 { use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; - use core::mem::transmute; unsafe { - let value = transmute(value); - transmute(_mm_aesdec_si128(value, transmute(xor))) + let value = transmute!(value); + transmute!(_mm_aesdec_si128(value, transmute!(xor))) } } @@ -160,11 +155,9 @@ pub(crate) fn aesdec(value: u128, xor: u128) -> u128 { use core::arch::aarch64::*; #[cfg(target_arch = "arm")] use core::arch::arm::*; - use core::mem::transmute; - unsafe { - let value = transmute(value); - transmute(vaesimcq_u8(vaesdq_u8(value, transmute(xor)))) - } + let res = unsafe { vaesimcq_u8(vaesdq_u8(transmute!(value), transmute!(0u128))) }; + let value: u128 = transmute!(res); + xor ^ value } #[allow(unused)] @@ -207,7 +200,7 @@ mod test { // #[cfg(target_arch = "x86_64")] // use core::arch::x86_64::*; // MASK.with(|mask| { - // unsafe { transmute(_mm_shuffle_epi8(transmute(a), transmute(mask.get()))) } + // unsafe { transmute!(_mm_shuffle_epi8(transmute!(a), transmute!(mask.get()))) } // }) // } // |