diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:07:41 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:07:41 +0000 |
commit | 874ad7e81d216b28411170ef275c1a8195dae750 (patch) | |
tree | 3ec70329241505385e9d7537477835c0f8a52581 | |
parent | 6c3d0062db5b878c9a03ae288667f543ad3931ef (diff) | |
parent | 6b3a6914c5e8a08bda8c1a24cd4366be7432a0d4 (diff) | |
download | memoffset-874ad7e81d216b28411170ef275c1a8195dae750.tar.gz |
Snap for 10453563 from 6b3a6914c5e8a08bda8c1a24cd4366be7432a0d4 to mainline-permission-releaseaml_per_341711000aml_per_341614000aml_per_341510010aml_per_341410020aml_per_341311000aml_per_341110020aml_per_341110010aml_per_341011100aml_per_341011020aml_per_340916010android14-mainline-permission-release
Change-Id: I90e1672256500377b773c276b54d3abc85e70cb5
-rw-r--r-- | .cargo_vcs_info.json | 7 | ||||
-rw-r--r-- | .github/workflows/ci.yml | 10 | ||||
-rw-r--r-- | Android.bp | 9 | ||||
-rw-r--r-- | Cargo.toml | 11 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | METADATA | 14 | ||||
-rw-r--r-- | README.md | 32 | ||||
-rw-r--r-- | TEST_MAPPING | 88 | ||||
-rw-r--r-- | build.rs | 3 | ||||
-rw-r--r-- | cargo2android.json | 2 | ||||
-rwxr-xr-x | ci/miri.sh | 14 | ||||
-rw-r--r-- | src/lib.rs | 5 | ||||
-rw-r--r-- | src/offset_of.rs | 82 | ||||
-rw-r--r-- | src/raw_field.rs | 109 | ||||
-rw-r--r-- | src/span_of.rs | 9 |
15 files changed, 286 insertions, 111 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index b737620..161d06e 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,6 @@ { "git": { - "sha1": "01e2e42ef0d833682c27b0f40a2cc748d86b2dc3" - } -} + "sha1": "0fac3ac6642dd017a36268c4cdba2f04ec050d11" + }, + "path_in_vcs": "" +}
\ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97fcf98..f82f7f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,7 @@ jobs: - 1.36.0 # Oldest supported with MaybeUninit - 1.40.0 # Oldest supported with cfg(doctest) - 1.51.0 # Oldest supported with ptr::addr_of! + - 1.65.0 # Oldest supported with stable const evaluation (sans cell) - stable - beta - nightly @@ -67,8 +68,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Install Miri + run: | + rustup toolchain install nightly --component miri + rustup override set nightly + cargo miri setup - name: Test with Miri - run: ci/miri.sh + run: | + cargo miri test + cargo miri test --all-features style: name: lints and formatting @@ -23,7 +23,7 @@ rust_library { host_supported: true, crate_name: "memoffset", cargo_env_compat: true, - cargo_pkg_version: "0.6.5", + cargo_pkg_version: "0.8.0", srcs: ["src/lib.rs"], edition: "2015", features: ["default"], @@ -32,14 +32,16 @@ rust_library { "doctests", "maybe_uninit", "raw_ref_macros", + "stable_const", "tuple_ty", ], apex_available: [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", "com.android.compos", "com.android.virt", ], + product_available: true, vendor_available: true, min_sdk_version: "29", } @@ -49,7 +51,7 @@ rust_test { host_supported: true, crate_name: "memoffset", cargo_env_compat: true, - cargo_pkg_version: "0.6.5", + cargo_pkg_version: "0.8.0", srcs: ["src/lib.rs"], test_suites: ["general-tests"], auto_gen_config: true, @@ -63,6 +65,7 @@ rust_test { "doctests", "maybe_uninit", "raw_ref_macros", + "stable_const", "tuple_ty", ], } @@ -11,16 +11,23 @@ [package] name = "memoffset" -version = "0.6.5" +version = "0.8.0" authors = ["Gilad Naaman <gilad.naaman@gmail.com>"] description = "offset_of functionality for Rust structs." readme = "README.md" -keywords = ["mem", "offset", "offset_of", "offsetof"] +keywords = [ + "mem", + "offset", + "offset_of", + "offsetof", +] categories = ["no-std"] license = "MIT" repository = "https://github.com/Gilnaa/memoffset" + [dev-dependencies.doc-comment] version = "0.3" + [build-dependencies.autocfg] version = "1" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 7a62858..71bdc9e 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "memoffset" -version = "0.6.5" +version = "0.8.0" authors = ["Gilad Naaman <gilad.naaman@gmail.com>"] description = "offset_of functionality for Rust structs." license = "MIT" @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/memoffset +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md + name: "memoffset" description: "offset_of functionality for Rust structs." third_party { @@ -7,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/memoffset/memoffset-0.6.5.crate" + value: "https://static.crates.io/crates/memoffset/memoffset-0.8.0.crate" } - version: "0.6.5" + version: "0.8.0" license_type: NOTICE last_upgrade_date { - year: 2022 - month: 3 - day: 1 + year: 2023 + month: 2 + day: 3 } } @@ -7,6 +7,7 @@ C-Like `offset_of` functionality for Rust structs. Introduces the following macros: * `offset_of!` for obtaining the offset of a member of a struct. * `offset_of_tuple!` for obtaining the offset of a member of a tuple. (Requires Rust 1.20+) + * `offset_of_union!` for obtaining the offset of a member of a union. * `span_of!` for obtaining the range that a field, or fields, span. `memoffset` works under `no_std` environments. @@ -16,7 +17,7 @@ Add the following dependency to your `Cargo.toml`: ```toml [dependencies] -memoffset = "0.6" +memoffset = "0.8" ``` These versions will compile fine with rustc versions greater or equal to 1.19. @@ -45,21 +46,40 @@ fn main() { } ``` -## Feature flags ## +## Usage in constants ## +`memoffset` has support for compile-time `offset_of!` on rust>=1.65, or on older nightly compilers. -### Usage in constants ### -`memoffset` has **experimental** support for compile-time `offset_of!` on a nightly compiler. +### Usage on stable Rust ### +Constant evaluation is automatically enabled and avilable on stable compilers starting with rustc 1.65. -In order to use it, you must enable the `unstable_const` crate feature and several compiler features. +This is an incomplete implementation with one caveat: +Due to dependence on [`#![feature(const_refs_to_cell)]`](https://github.com/rust-lang/rust/issues/80384), you cannot get the offset of a `Cell` field in a const-context. + +This means that if need to get the offset of a cell, you'll have to remain on nightly for now. + +### Usage on recent nightlies ### + +If you're using a new-enough nightly and you require the ability to get the offset of a `Cell`, +you'll have to enable the `unstable_const` cargo feature, as well as enabling `const_refs_to_cell` in your crate root. + +Do note that `unstable_const` is an unstable feature that is set to be removed in a future version of `memoffset`. Cargo.toml: ```toml [dependencies.memoffset] -version = "0.6" +version = "0.8" features = ["unstable_const"] ``` Your crate root: (`lib.rs`/`main.rs`) ```rust,ignore +#![feature(const_refs_to_cell)] +``` + +### Usage on older nightlies ### +In order to use it on an older nightly compiler, you must enable the `unstable_const` crate feature and several compiler features. + +Your crate root: (`lib.rs`/`main.rs`) +```rust,ignore #![feature(const_ptr_offset_from, const_refs_to_cell)] ``` diff --git a/TEST_MAPPING b/TEST_MAPPING index 83479e2..448ea8a 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -11,6 +11,9 @@ "path": "external/rust/crates/crossbeam-epoch" }, { + "path": "external/rust/crates/hashbrown" + }, + { "path": "external/rust/crates/tinytemplate" }, { @@ -21,106 +24,55 @@ }, { "path": "external/rust/crates/unicode-xid" - } - ], - "presubmit": [ - { - "name": "ZipFuseTest" }, { - "name": "apkdmverity.test" + "path": "packages/modules/Virtualization/apkdmverity" }, { - "name": "authfs_device_test_src_lib" + "path": "packages/modules/Virtualization/authfs" }, { - "name": "diced_open_dice_cbor_test" + "path": "packages/modules/Virtualization/encryptedstore" }, { - "name": "diced_sample_inputs_test" + "path": "packages/modules/Virtualization/libs/capabilities" }, { - "name": "diced_test" + "path": "packages/modules/Virtualization/libs/devicemapper" }, { - "name": "diced_utils_test" + "path": "packages/modules/Virtualization/microdroid_manager" }, { - "name": "diced_vendor_test" + "path": "packages/modules/Virtualization/virtualizationmanager" }, { - "name": "keystore2_crypto_test_rust" + "path": "packages/modules/Virtualization/vm" }, { - "name": "keystore2_selinux_concurrency_test" + "path": "packages/modules/Virtualization/zipfuse" }, { - "name": "keystore2_test" + "path": "system/security/diced" }, { - "name": "keystore2_test_utils_test" + "path": "system/security/keystore2" }, { - "name": "legacykeystore_test" + "path": "system/security/keystore2/legacykeystore" }, { - "name": "memoffset_test_src_lib" - }, - { - "name": "microdroid_manager_test" - }, + "path": "system/security/keystore2/src/crypto" + } + ], + "presubmit": [ { - "name": "virtualizationservice_device_test" + "name": "memoffset_test_src_lib" } ], "presubmit-rust": [ { - "name": "ZipFuseTest" - }, - { - "name": "apkdmverity.test" - }, - { - "name": "authfs_device_test_src_lib" - }, - { - "name": "diced_open_dice_cbor_test" - }, - { - "name": "diced_sample_inputs_test" - }, - { - "name": "diced_test" - }, - { - "name": "diced_utils_test" - }, - { - "name": "diced_vendor_test" - }, - { - "name": "keystore2_crypto_test_rust" - }, - { - "name": "keystore2_selinux_concurrency_test" - }, - { - "name": "keystore2_test" - }, - { - "name": "keystore2_test_utils_test" - }, - { - "name": "legacykeystore_test" - }, - { "name": "memoffset_test_src_lib" - }, - { - "name": "microdroid_manager_test" - }, - { - "name": "virtualizationservice_device_test" } ] } @@ -19,4 +19,7 @@ fn main() { if ac.probe_rustc_version(1, 51) { println!("cargo:rustc-cfg=raw_ref_macros"); } + if ac.probe_rustc_version(1, 65) { + println!("cargo:rustc-cfg=stable_const"); + } } diff --git a/cargo2android.json b/cargo2android.json index 5654962..b318e12 100644 --- a/cargo2android.json +++ b/cargo2android.json @@ -1,7 +1,7 @@ { "apex-available": [ "//apex_available:platform", - "com.android.bluetooth", + "com.android.btservices", "com.android.compos", "com.android.virt" ], diff --git a/ci/miri.sh b/ci/miri.sh deleted file mode 100755 index 5aea2ec..0000000 --- a/ci/miri.sh +++ /dev/null @@ -1,14 +0,0 @@ -set -ex - -# Install Miri. -MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) -echo "Installing latest nightly with Miri: $MIRI_NIGHTLY" -rustup default "$MIRI_NIGHTLY" -rustup component add miri - -# Run tests. -cargo miri test -cargo miri test --all-features - -# Restore old state in case Travis uses this cache for other jobs. -rustup default nightly @@ -58,9 +58,10 @@ // ANDROID: include standard library to build as a dylib //#![no_std] #![cfg_attr( - feature = "unstable_const", - feature(const_ptr_offset_from, const_refs_to_cell) + all(feature = "unstable_const", not(stable_const)), + feature(const_ptr_offset_from) )] +#![cfg_attr(feature = "unstable_const", feature(const_refs_to_cell))] #[macro_use] #[cfg(doctests)] diff --git a/src/offset_of.rs b/src/offset_of.rs index 8596e45..9ce4ae2 100644 --- a/src/offset_of.rs +++ b/src/offset_of.rs @@ -46,7 +46,7 @@ macro_rules! _memoffset__let_base_ptr { } /// Macro to compute the distance between two pointers. -#[cfg(feature = "unstable_const")] +#[cfg(any(feature = "unstable_const", stable_const))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset_offset_from_unsafe { @@ -58,7 +58,7 @@ macro_rules! _memoffset_offset_from_unsafe { unsafe { (field as *const u8).offset_from(base as *const u8) as usize } }}; } -#[cfg(not(feature = "unstable_const"))] +#[cfg(not(any(feature = "unstable_const", stable_const)))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset_offset_from_unsafe { @@ -86,6 +86,16 @@ macro_rules! _memoffset_offset_from_unsafe { /// assert_eq!(offset_of!(Foo, b), 4); /// } /// ``` +/// +/// ## Notes +/// Rust's ABI is unstable, and [type layout can be changed with each +/// compilation](https://doc.rust-lang.org/reference/type-layout.html). +/// +/// Using `offset_of!` with a `repr(Rust)` struct will return the correct offset of the +/// specified `field` for a particular compilation, but the exact value may change +/// based on the compiler version, concrete struct type, time of day, or rustc's mood. +/// +/// As a result, the value should not be retained and used between different compilations. #[macro_export(local_inner_macros)] macro_rules! offset_of { ($parent:path, $field:tt) => {{ @@ -121,6 +131,39 @@ macro_rules! offset_of_tuple { }}; } +/// Calculates the offset of the specified union member from the start of the union. +/// +/// ## Examples +/// ``` +/// use memoffset::offset_of_union; +/// +/// #[repr(C, packed)] +/// union Foo { +/// foo32: i32, +/// foo64: i64, +/// } +/// +/// fn main() { +/// assert!(offset_of_union!(Foo, foo64) == 0); +/// } +/// ``` +/// +/// ## Note +/// Due to macro_rules limitations, this macro will accept structs with a single field as well as unions. +/// This is not a stable guarantee, and future versions of this crate might fail +/// on any use of this macro with a struct, without a semver bump. +#[macro_export(local_inner_macros)] +macro_rules! offset_of_union { + ($parent:path, $field:tt) => {{ + // Get a base pointer (non-dangling if rustc supports `MaybeUninit`). + _memoffset__let_base_ptr!(base_ptr, $parent); + // Get field pointer. + let field_ptr = raw_field_union!(base_ptr, $parent, $field); + // Compute offset. + _memoffset_offset_from_unsafe!(field_ptr, base_ptr) + }}; +} + #[cfg(test)] mod tests { #[test] @@ -162,6 +205,21 @@ mod tests { } #[test] + fn offset_union() { + // Since we're specifying repr(C), all fields are supposed to be at offset 0 + #[repr(C)] + union Foo { + a: u32, + b: [u8; 2], + c: i64, + } + + assert_eq!(offset_of_union!(Foo, a), 0); + assert_eq!(offset_of_union!(Foo, b), 0); + assert_eq!(offset_of_union!(Foo, c), 0); + } + + #[test] fn path() { mod sub { #[repr(C)] @@ -238,7 +296,23 @@ mod tests { ); } - #[cfg(feature = "unstable_const")] + #[test] + fn test_raw_field_union() { + #[repr(C)] + union Foo { + a: u32, + b: [u8; 2], + c: i64, + } + + let f = Foo { a: 0 }; + let f_ptr = &f as *const _; + assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, a) as usize); + assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, b) as usize); + assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, c) as usize); + } + + #[cfg(any(feature = "unstable_const", stable_const))] #[test] fn const_offset() { #[repr(C)] @@ -263,7 +337,7 @@ mod tests { assert_eq!([0; offset_of!(Foo, b)].len(), 4); } - #[cfg(feature = "unstable_const")] + #[cfg(any(feature = "unstable_const", stable_const))] #[test] fn const_fn_offset() { const fn test_fn() -> usize { diff --git a/src/raw_field.rs b/src/raw_field.rs index a8dd2b3..e16df9f 100644 --- a/src/raw_field.rs +++ b/src/raw_field.rs @@ -39,6 +39,21 @@ macro_rules! _memoffset__addr_of { } /// Deref-coercion protection macro. +/// +/// Prevents complilation if the specified field name is not a part of the +/// struct definition. +/// +/// ```compile_fail +/// use memoffset::_memoffset__field_check; +/// +/// struct Foo { +/// foo: i32, +/// } +/// +/// type BoxedFoo = Box<Foo>; +/// +/// _memoffset__field_check!(BoxedFoo, foo); +/// ``` #[cfg(allow_clippy)] #[macro_export] #[doc(hidden)] @@ -64,6 +79,25 @@ macro_rules! _memoffset__field_check { } /// Deref-coercion protection macro. +/// +/// Prevents complilation if the specified type is not a tuple. +/// +/// ```compile_fail +/// use memoffset::_memoffset__field_check_tuple; +/// +/// _memoffset__field_check_tuple!(i32, 0); +/// ``` +#[cfg(allow_clippy)] +#[macro_export] +#[doc(hidden)] +macro_rules! _memoffset__field_check_tuple { + ($type:ty, $field:tt) => { + // Make sure the type argument is a tuple + #[allow(clippy::unneeded_wildcard_pattern)] + let (_, ..): $type; + }; +} +#[cfg(not(allow_clippy))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_tuple { @@ -73,6 +107,53 @@ macro_rules! _memoffset__field_check_tuple { }; } +/// Deref-coercion protection macro for unions. +/// Unfortunately accepts single-field structs as well, which is not ideal, +/// but ultimately pretty harmless. +/// +/// ```compile_fail +/// use memoffset::_memoffset__field_check_union; +/// +/// union Foo { +/// variant_a: i32, +/// } +/// +/// type BoxedFoo = Box<Foo>; +/// +/// _memoffset__field_check_union!(BoxedFoo, variant_a); +/// ``` +#[cfg(allow_clippy)] +#[macro_export] +#[doc(hidden)] +macro_rules! _memoffset__field_check_union { + ($type:path, $field:tt) => { + // Make sure the field actually exists. This line ensures that a + // compile-time error is generated if $field is accessed through a + // Deref impl. + #[allow(clippy::unneeded_wildcard_pattern)] + // rustc1.19 requires unsafe here for the pattern; not needed in newer versions + #[allow(unused_unsafe)] + unsafe { + let $type { $field: _ }; + } + }; +} +#[cfg(not(allow_clippy))] +#[macro_export] +#[doc(hidden)] +macro_rules! _memoffset__field_check_union { + ($type:path, $field:tt) => { + // Make sure the field actually exists. This line ensures that a + // compile-time error is generated if $field is accessed through a + // Deref impl. + // rustc1.19 requires unsafe here for the pattern; not needed in newer versions + #[allow(unused_unsafe)] + unsafe { + let $type { $field: _ }; + } + }; +} + /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent type. /// @@ -115,3 +196,31 @@ macro_rules! raw_field_tuple { } }}; } + +/// Computes a const raw pointer to the given field of the given base pointer +/// to the given parent tuple typle. +/// +/// The `base` pointer *must not* be dangling, but it *may* point to +/// uninitialized memory. +/// +/// ## Note +/// This macro is the same as `raw_field`, except for a different Deref-coercion check that +/// supports unions. +/// Due to macro_rules limitations, this check will accept structs with a single field as well as unions. +/// This is not a stable guarantee, and future versions of this crate might fail +/// on any use of this macro with a struct, without a semver bump. +#[macro_export(local_inner_macros)] +macro_rules! raw_field_union { + ($base:expr, $parent:path, $field:tt) => {{ + _memoffset__field_check_union!($parent, $field); + let base = $base; // evaluate $base outside the `unsafe` block + + // Get the field address. + // Crucially, we know that this will not trigger a deref coercion because + // of the field check we did above. + #[allow(unused_unsafe)] // for when the macro is used in an unsafe block + unsafe { + _memoffset__addr_of!((*(base as *const $parent)).$field) + } + }}; +} diff --git a/src/span_of.rs b/src/span_of.rs index a3663d5..c2030b7 100644 --- a/src/span_of.rs +++ b/src/span_of.rs @@ -52,11 +52,18 @@ macro_rules! _memoffset__compile_error { /// span_of!(Struct, start ..) /// ``` /// -/// *Note*: +/// ### Note /// This macro uses recursion in order to resolve the range expressions, so there is a limit to /// the complexity of the expression. /// In order to raise the limit, the compiler's recursion limit should be lifted. /// +/// ### Safety +/// The inter-field form mentioned above assumes that the first field is positioned before the +/// second. +/// This is only guarenteed for `repr(C)` structs. +/// Usage with `repr(Rust)` structs may yield unexpected results, like downward-going ranges, +/// spans that include unexpected fields, empty spans, or spans that include *unexpected* padding bytes. +/// /// ## Examples /// ``` /// use memoffset::span_of; |