diff options
author | Patrick J Volkerding <volkerdi@slackware.com> | 2022-12-16 04:46:51 +0000 |
---|---|---|
committer | Eric Hameleers <alien@slackware.com> | 2022-12-16 06:38:01 +0100 |
commit | 7852409378db9d911b949481c914726d20a97408 (patch) | |
tree | 8ae38346ec10f5a9a082dc13140dda93d05cdcc4 /source/xap/mozilla-firefox/8f889cf198ae7ffa9341423cb5a07ed39c07463a.patch | |
parent | fc0ff5a5d7c45f929eb214b3147aa538e736e2aa (diff) | |
download | current-7852409378db9d911b949481c914726d20a97408.tar.gz current-7852409378db9d911b949481c914726d20a97408.tar.xz |
Fri Dec 16 04:46:51 UTC 202220221216044651
d/help2man-1.49.3-x86_64-1.txz: Upgraded.
l/pipewire-0.3.63-x86_64-1.txz: Upgraded.
x/libX11-1.8.3-x86_64-1.txz: Upgraded.
x/mesa-22.3.1-x86_64-1.txz: Upgraded.
xap/mozilla-firefox-108.0-x86_64-1.txz: Upgraded.
This update contains security fixes and improvements.
Thanks to marav for the build help.
For more information, see:
https://www.mozilla.org/en-US/firefox/108.0/releasenotes/
https://www.mozilla.org/en-US/security/advisories/mfsa2022-51/
https://www.cve.org/CVERecord?id=CVE-2022-46871
https://www.cve.org/CVERecord?id=CVE-2022-46872
https://www.cve.org/CVERecord?id=CVE-2022-46873
https://www.cve.org/CVERecord?id=CVE-2022-46874
https://www.cve.org/CVERecord?id=CVE-2022-46875
https://www.cve.org/CVERecord?id=CVE-2022-46877
https://www.cve.org/CVERecord?id=CVE-2022-46878
https://www.cve.org/CVERecord?id=CVE-2022-46879
(* Security fix *)
Diffstat (limited to 'source/xap/mozilla-firefox/8f889cf198ae7ffa9341423cb5a07ed39c07463a.patch')
-rw-r--r-- | source/xap/mozilla-firefox/8f889cf198ae7ffa9341423cb5a07ed39c07463a.patch | 801 |
1 files changed, 801 insertions, 0 deletions
diff --git a/source/xap/mozilla-firefox/8f889cf198ae7ffa9341423cb5a07ed39c07463a.patch b/source/xap/mozilla-firefox/8f889cf198ae7ffa9341423cb5a07ed39c07463a.patch new file mode 100644 index 000000000..89e7c12b8 --- /dev/null +++ b/source/xap/mozilla-firefox/8f889cf198ae7ffa9341423cb5a07ed39c07463a.patch @@ -0,0 +1,801 @@ +From 8f889cf198ae7ffa9341423cb5a07ed39c07463a Mon Sep 17 00:00:00 2001 +From: Mike Hommey <mh@glandium.org> +Date: Thu, 15 Dec 2022 16:36:52 +0900 +Subject: [PATCH] Replace the use of Hash with a custom trait + +The custom trait is expected to consistently give the result that Hash +gives on 64-bits little-endian, but on all platforms +--- + uniffi_bindgen/src/interface/attributes.rs | 19 ++-- + uniffi_bindgen/src/interface/callbacks.rs | 11 +- + uniffi_bindgen/src/interface/enum_.rs | 5 +- + uniffi_bindgen/src/interface/error.rs | 3 +- + uniffi_bindgen/src/interface/function.rs | 17 ++-- + uniffi_bindgen/src/interface/literal.rs | 11 +- + uniffi_bindgen/src/interface/mod.rs | 28 +++--- + uniffi_bindgen/src/interface/object.rs | 37 +++---- + uniffi_bindgen/src/interface/record.rs | 5 +- + uniffi_bindgen/src/interface/types/mod.rs | 3 +- + uniffi_checksum_derive/Cargo.toml | 22 ++++ + uniffi_checksum_derive/src/lib.rs | 111 +++++++++++++++++++++ + uniffi_meta/Cargo.toml | 1 + + uniffi_meta/src/lib.rs | 89 +++++++++++++++-- + 14 files changed, 288 insertions(+), 74 deletions(-) + create mode 100644 uniffi_checksum_derive/Cargo.toml + create mode 100644 uniffi_checksum_derive/src/lib.rs + +diff --git a/uniffi_bindgen/src/interface/attributes.rs b/uniffi_bindgen/src/interface/attributes.rs +index 49b885520..3c9bd522b 100644 +--- a/uniffi_bindgen/src/interface/attributes.rs ++++ b/uniffi_bindgen/src/interface/attributes.rs +@@ -15,13 +15,14 @@ + //! if we grow significantly more complicated attribute handling. + + use anyhow::{bail, Result}; ++use uniffi_meta::Checksum; + + /// Represents an attribute parsed from UDL, like `[ByRef]` or `[Throws]`. + /// + /// This is a convenience enum for parsing UDL attributes and erroring out if we encounter + /// any unsupported ones. These don't convert directly into parts of a `ComponentInterface`, but + /// may influence the properties of things like functions and arguments. +-#[derive(Debug, Clone, Hash)] ++#[derive(Debug, Clone, Checksum)] + pub(super) enum Attribute { + ByRef, + Enum, +@@ -119,7 +120,7 @@ where + + /// Attributes that can be attached to an `enum` definition in the UDL. + /// There's only one case here: using `[Error]` to mark an enum as an error class. +-#[derive(Debug, Clone, Hash, Default)] ++#[derive(Debug, Clone, Checksum, Default)] + pub(super) struct EnumAttributes(Vec<Attribute>); + + impl EnumAttributes { +@@ -155,7 +156,7 @@ impl<T: TryInto<EnumAttributes, Error = anyhow::Error>> TryFrom<Option<T>> for E + /// + /// This supports the `[Throws=ErrorName]` attribute for functions that + /// can produce an error. +-#[derive(Debug, Clone, Hash, Default)] ++#[derive(Debug, Clone, Checksum, Default)] + pub(super) struct FunctionAttributes(Vec<Attribute>); + + impl FunctionAttributes { +@@ -198,7 +199,7 @@ impl<T: TryInto<FunctionAttributes, Error = anyhow::Error>> TryFrom<Option<T>> + /// + /// This supports the `[ByRef]` attribute for arguments that should be passed + /// by reference in the generated Rust scaffolding. +-#[derive(Debug, Clone, Hash, Default)] ++#[derive(Debug, Clone, Checksum, Default)] + pub(super) struct ArgumentAttributes(Vec<Attribute>); + + impl ArgumentAttributes { +@@ -233,7 +234,7 @@ impl<T: TryInto<ArgumentAttributes, Error = anyhow::Error>> TryFrom<Option<T>> + } + + /// Represents UDL attributes that might appear on an `interface` definition. +-#[derive(Debug, Clone, Hash, Default)] ++#[derive(Debug, Clone, Checksum, Default)] + pub(super) struct InterfaceAttributes(Vec<Attribute>); + + impl InterfaceAttributes { +@@ -287,7 +288,7 @@ impl<T: TryInto<InterfaceAttributes, Error = anyhow::Error>> TryFrom<Option<T>> + /// + /// This supports the `[Throws=ErrorName]` attribute for constructors that can produce + /// an error, and the `[Name=MethodName]` for non-default constructors. +-#[derive(Debug, Clone, Hash, Default)] ++#[derive(Debug, Clone, Checksum, Default)] + pub(super) struct ConstructorAttributes(Vec<Attribute>); + + impl ConstructorAttributes { +@@ -326,7 +327,7 @@ impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for ConstructorAttri + /// + /// This supports the `[Throws=ErrorName]` attribute for methods that can produce + /// an error, and the `[Self=ByArc]` attribute for methods that take `Arc<Self>` as receiver. +-#[derive(Debug, Clone, Hash, Default)] ++#[derive(Debug, Clone, Checksum, Default)] + pub(super) struct MethodAttributes(Vec<Attribute>); + + impl MethodAttributes { +@@ -375,7 +376,7 @@ impl<T: TryInto<MethodAttributes, Error = anyhow::Error>> TryFrom<Option<T>> for + /// Actually we only support one of these right now, `[Self=ByArc]`. + /// We might add more in future, e.g. a `[Self=ByRef]` if there are cases + /// where we need to force the receiver to be taken by reference. +-#[derive(Debug, Clone, Hash)] ++#[derive(Debug, Clone, Checksum)] + pub(super) enum SelfType { + ByArc, // Method receiver is `Arc<Self>`. + } +@@ -398,7 +399,7 @@ impl TryFrom<&weedle::attribute::IdentifierOrString<'_>> for SelfType { + /// Represents UDL attributes that might appear on a typedef + /// + /// This supports the `[External="crate_name"]` and `[Custom]` attributes for types. +-#[derive(Debug, Clone, Hash, Default)] ++#[derive(Debug, Clone, Checksum, Default)] + pub(super) struct TypedefAttributes(Vec<Attribute>); + + impl TypedefAttributes { +diff --git a/uniffi_bindgen/src/interface/callbacks.rs b/uniffi_bindgen/src/interface/callbacks.rs +index 654652afe..886f02b29 100644 +--- a/uniffi_bindgen/src/interface/callbacks.rs ++++ b/uniffi_bindgen/src/interface/callbacks.rs +@@ -33,9 +33,10 @@ + //! # Ok::<(), anyhow::Error>(()) + //! ``` + +-use std::hash::{Hash, Hasher}; ++use std::hash::Hasher; + + use anyhow::{bail, Result}; ++use uniffi_meta::Checksum; + + use super::ffi::{FFIArgument, FFIFunction, FFIType}; + use super::object::Method; +@@ -88,16 +89,16 @@ impl CallbackInterface { + } + } + +-impl Hash for CallbackInterface { +- fn hash<H: Hasher>(&self, state: &mut H) { ++impl Checksum for CallbackInterface { ++ fn checksum<H: Hasher>(&self, state: &mut H) { + // We don't include the FFIFunc in the hash calculation, because: + // - it is entirely determined by the other fields, + // so excluding it is safe. + // - its `name` property includes a checksum derived from the very + // hash value we're trying to calculate here, so excluding it + // avoids a weird circular depenendency in the calculation. +- self.name.hash(state); +- self.methods.hash(state); ++ self.name.checksum(state); ++ self.methods.checksum(state); + } + } + +diff --git a/uniffi_bindgen/src/interface/enum_.rs b/uniffi_bindgen/src/interface/enum_.rs +index 04eba0d25..b8fe0ddd7 100644 +--- a/uniffi_bindgen/src/interface/enum_.rs ++++ b/uniffi_bindgen/src/interface/enum_.rs +@@ -77,6 +77,7 @@ + //! ``` + + use anyhow::{bail, Result}; ++use uniffi_meta::Checksum; + + use super::record::Field; + use super::types::{Type, TypeIterator}; +@@ -87,7 +88,7 @@ use super::{APIConverter, ComponentInterface}; + /// + /// Enums are passed across the FFI by serializing to a bytebuffer, with a + /// i32 indicating the variant followed by the serialization of each field. +-#[derive(Debug, Clone, Hash)] ++#[derive(Debug, Clone, Checksum)] + pub struct Enum { + pub(super) name: String, + pub(super) variants: Vec<Variant>, +@@ -174,7 +175,7 @@ impl APIConverter<Enum> for weedle::InterfaceDefinition<'_> { + /// Represents an individual variant in an Enum. + /// + /// Each variant has a name and zero or more fields. +-#[derive(Debug, Clone, Default, Hash)] ++#[derive(Debug, Clone, Default, Checksum)] + pub struct Variant { + pub(super) name: String, + pub(super) fields: Vec<Field>, +diff --git a/uniffi_bindgen/src/interface/error.rs b/uniffi_bindgen/src/interface/error.rs +index 7e9b571a1..adae769f0 100644 +--- a/uniffi_bindgen/src/interface/error.rs ++++ b/uniffi_bindgen/src/interface/error.rs +@@ -83,6 +83,7 @@ + //! ``` + + use anyhow::Result; ++use uniffi_meta::Checksum; + + use super::enum_::{Enum, Variant}; + use super::types::{Type, TypeIterator}; +@@ -94,7 +95,7 @@ use super::{APIConverter, ComponentInterface}; + /// they're handled in the FFI very differently. We create them in `uniffi::call_with_result()` if + /// the wrapped function returns an `Err` value + /// struct and assign an integer error code to each variant. +-#[derive(Debug, Clone, Hash)] ++#[derive(Debug, Clone, Checksum)] + pub struct Error { + pub name: String, + enum_: Enum, +diff --git a/uniffi_bindgen/src/interface/function.rs b/uniffi_bindgen/src/interface/function.rs +index 4eff0795c..869c1b59b 100644 +--- a/uniffi_bindgen/src/interface/function.rs ++++ b/uniffi_bindgen/src/interface/function.rs +@@ -32,9 +32,10 @@ + //! # Ok::<(), anyhow::Error>(()) + //! ``` + use std::convert::TryFrom; +-use std::hash::{Hash, Hasher}; ++use std::hash::Hasher; + + use anyhow::{bail, Result}; ++use uniffi_meta::Checksum; + + use super::ffi::{FFIArgument, FFIFunction}; + use super::literal::{convert_default_value, Literal}; +@@ -142,18 +143,18 @@ impl From<uniffi_meta::FnMetadata> for Function { + } + } + +-impl Hash for Function { +- fn hash<H: Hasher>(&self, state: &mut H) { ++impl Checksum for Function { ++ fn checksum<H: Hasher>(&self, state: &mut H) { + // We don't include the FFIFunc in the hash calculation, because: + // - it is entirely determined by the other fields, + // so excluding it is safe. + // - its `name` property includes a checksum derived from the very + // hash value we're trying to calculate here, so excluding it + // avoids a weird circular depenendency in the calculation. +- self.name.hash(state); +- self.arguments.hash(state); +- self.return_type.hash(state); +- self.attributes.hash(state); ++ self.name.checksum(state); ++ self.arguments.checksum(state); ++ self.return_type.checksum(state); ++ self.attributes.checksum(state); + } + } + +@@ -185,7 +186,7 @@ impl APIConverter<Function> for weedle::namespace::OperationNamespaceMember<'_> + /// Represents an argument to a function/constructor/method call. + /// + /// Each argument has a name and a type, along with some optional metadata. +-#[derive(Debug, Clone, Hash)] ++#[derive(Debug, Clone, Checksum)] + pub struct Argument { + pub(super) name: String, + pub(super) type_: Type, +diff --git a/uniffi_bindgen/src/interface/literal.rs b/uniffi_bindgen/src/interface/literal.rs +index 8b333c614..1aa1c8785 100644 +--- a/uniffi_bindgen/src/interface/literal.rs ++++ b/uniffi_bindgen/src/interface/literal.rs +@@ -8,12 +8,13 @@ + //! which appear in places such as default arguments. + + use anyhow::{bail, Result}; ++use uniffi_meta::Checksum; + + use super::types::Type; + + // Represents a literal value. + // Used for e.g. default argument values. +-#[derive(Debug, Clone, Hash)] ++#[derive(Debug, Clone, Checksum)] + pub enum Literal { + Boolean(bool), + String(String), +@@ -35,13 +36,19 @@ pub enum Literal { + + // Represent the radix of integer literal values. + // We preserve the radix into the generated bindings for readability reasons. +-#[derive(Debug, Clone, Copy, Hash)] ++#[derive(Debug, Clone, Copy)] + pub enum Radix { + Decimal = 10, + Octal = 8, + Hexadecimal = 16, + } + ++impl Checksum for Radix { ++ fn checksum<H: ::core::hash::Hasher>(&self, state: &mut H) { ++ state.write(&(*self as u64).to_le_bytes()); ++ } ++} ++ + pub(super) fn convert_default_value( + default_value: &weedle::literal::DefaultValue<'_>, + type_: &Type, +diff --git a/uniffi_bindgen/src/interface/mod.rs b/uniffi_bindgen/src/interface/mod.rs +index 9aa92e9b0..eb40ea3fd 100644 +--- a/uniffi_bindgen/src/interface/mod.rs ++++ b/uniffi_bindgen/src/interface/mod.rs +@@ -47,7 +47,7 @@ + use std::{ + collections::HashSet, + convert::TryFrom, +- hash::{Hash, Hasher}, ++ hash::Hasher, + iter, + }; + +@@ -77,7 +77,7 @@ pub use record::{Field, Record}; + + pub mod ffi; + pub use ffi::{FFIArgument, FFIFunction, FFIType}; +-use uniffi_meta::{MethodMetadata, ObjectMetadata}; ++use uniffi_meta::{Checksum, MethodMetadata, ObjectMetadata}; + + /// The main public interface for this module, representing the complete details of an interface exposed + /// by a rust component and the details of consuming it via an extern-C FFI layer. +@@ -672,20 +672,16 @@ impl ComponentInterface { + } + } + +-/// `ComponentInterface` structs can be hashed, but this is mostly a convenient way to +-/// produce a checksum of their contents. They're not really intended to live in a hashtable. +-impl Hash for ComponentInterface { +- fn hash<H: Hasher>(&self, state: &mut H) { +- // We can't hash `self.types`, but its contents are implied by the other fields +- // anyway, so it's safe to ignore it. +- self.uniffi_version.hash(state); +- self.namespace.hash(state); +- self.enums.hash(state); +- self.records.hash(state); +- self.functions.hash(state); +- self.objects.hash(state); +- self.callback_interfaces.hash(state); +- self.errors.hash(state); ++impl Checksum for ComponentInterface { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ Checksum::checksum(&self.uniffi_version, state); ++ Checksum::checksum(&self.namespace, state); ++ Checksum::checksum(&self.enums, state); ++ Checksum::checksum(&self.records, state); ++ Checksum::checksum(&self.functions, state); ++ Checksum::checksum(&self.objects, state); ++ Checksum::checksum(&self.callback_interfaces, state); ++ Checksum::checksum(&self.errors, state); + } + } + +diff --git a/uniffi_bindgen/src/interface/object.rs b/uniffi_bindgen/src/interface/object.rs +index e366123b5..3bd6bfabe 100644 +--- a/uniffi_bindgen/src/interface/object.rs ++++ b/uniffi_bindgen/src/interface/object.rs +@@ -58,10 +58,11 @@ + //! ``` + + use std::convert::TryFrom; +-use std::hash::{Hash, Hasher}; ++use std::hash::Hasher; + use std::{collections::HashSet, iter}; + + use anyhow::{bail, Result}; ++use uniffi_meta::Checksum; + + use super::ffi::{FFIArgument, FFIFunction, FFIType}; + use super::function::Argument; +@@ -190,17 +191,17 @@ impl Object { + } + } + +-impl Hash for Object { +- fn hash<H: Hasher>(&self, state: &mut H) { ++impl Checksum for Object { ++ fn checksum<H: Hasher>(&self, state: &mut H) { + // We don't include the FFIFunc in the hash calculation, because: + // - it is entirely determined by the other fields, + // so excluding it is safe. + // - its `name` property includes a checksum derived from the very + // hash value we're trying to calculate here, so excluding it + // avoids a weird circular depenendency in the calculation. +- self.name.hash(state); +- self.constructors.hash(state); +- self.methods.hash(state); ++ self.name.checksum(state); ++ self.constructors.checksum(state); ++ self.methods.checksum(state); + } + } + +@@ -299,17 +300,17 @@ impl Constructor { + } + } + +-impl Hash for Constructor { +- fn hash<H: Hasher>(&self, state: &mut H) { ++impl Checksum for Constructor { ++ fn checksum<H: Hasher>(&self, state: &mut H) { + // We don't include the FFIFunc in the hash calculation, because: + // - it is entirely determined by the other fields, + // so excluding it is safe. + // - its `name` property includes a checksum derived from the very + // hash value we're trying to calculate here, so excluding it + // avoids a weird circular depenendency in the calculation. +- self.name.hash(state); +- self.arguments.hash(state); +- self.attributes.hash(state); ++ self.name.checksum(state); ++ self.arguments.checksum(state); ++ self.attributes.checksum(state); + } + } + +@@ -450,19 +451,19 @@ impl From<uniffi_meta::MethodMetadata> for Method { + } + } + +-impl Hash for Method { +- fn hash<H: Hasher>(&self, state: &mut H) { ++impl Checksum for Method { ++ fn checksum<H: Hasher>(&self, state: &mut H) { + // We don't include the FFIFunc in the hash calculation, because: + // - it is entirely determined by the other fields, + // so excluding it is safe. + // - its `name` property includes a checksum derived from the very + // hash value we're trying to calculate here, so excluding it + // avoids a weird circular depenendency in the calculation. +- self.name.hash(state); +- self.object_name.hash(state); +- self.arguments.hash(state); +- self.return_type.hash(state); +- self.attributes.hash(state); ++ self.name.checksum(state); ++ self.object_name.checksum(state); ++ self.arguments.checksum(state); ++ self.return_type.checksum(state); ++ self.attributes.checksum(state); + } + } + +diff --git a/uniffi_bindgen/src/interface/record.rs b/uniffi_bindgen/src/interface/record.rs +index c55200eb1..dd6a48e2c 100644 +--- a/uniffi_bindgen/src/interface/record.rs ++++ b/uniffi_bindgen/src/interface/record.rs +@@ -45,6 +45,7 @@ + //! ``` + + use anyhow::{bail, Result}; ++use uniffi_meta::Checksum; + + use super::types::{Type, TypeIterator}; + use super::{ +@@ -58,7 +59,7 @@ use super::{APIConverter, ComponentInterface}; + /// In the FFI these are represented as a byte buffer, which one side explicitly + /// serializes the data into and the other serializes it out of. So I guess they're + /// kind of like "pass by clone" values. +-#[derive(Debug, Clone, Hash)] ++#[derive(Debug, Clone, Checksum)] + pub struct Record { + pub(super) name: String, + pub(super) fields: Vec<Field>, +@@ -109,7 +110,7 @@ impl APIConverter<Record> for weedle::DictionaryDefinition<'_> { + } + + // Represents an individual field on a Record. +-#[derive(Debug, Clone, Hash)] ++#[derive(Debug, Clone, Checksum)] + pub struct Field { + pub(super) name: String, + pub(super) type_: Type, +diff --git a/uniffi_bindgen/src/interface/types/mod.rs b/uniffi_bindgen/src/interface/types/mod.rs +index 8a0131c9f..65426926f 100644 +--- a/uniffi_bindgen/src/interface/types/mod.rs ++++ b/uniffi_bindgen/src/interface/types/mod.rs +@@ -25,6 +25,7 @@ use std::{collections::hash_map::Entry, collections::BTreeSet, collections::Hash + + use anyhow::{bail, Result}; + use heck::ToUpperCamelCase; ++use uniffi_meta::Checksum; + + use super::ffi::FFIType; + +@@ -36,7 +37,7 @@ pub(super) use resolver::{resolve_builtin_type, TypeResolver}; + /// Represents all the different high-level types that can be used in a component interface. + /// At this level we identify user-defined types by name, without knowing any details + /// of their internal structure apart from what type of thing they are (record, enum, etc). +-#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] ++#[derive(Debug, Clone, Eq, PartialEq, Checksum, Ord, PartialOrd)] + pub enum Type { + // Primitive types. + UInt8, +diff --git a/uniffi_checksum_derive/Cargo.toml b/uniffi_checksum_derive/Cargo.toml +new file mode 100644 +index 000000000..a04c31aab +--- /dev/null ++++ b/uniffi_checksum_derive/Cargo.toml +@@ -0,0 +1,22 @@ ++[package] ++name = "uniffi_checksum_derive" ++version = "0.21.0" ++authors = ["Firefox Sync Team <sync-team@mozilla.com>"] ++description = "a multi-language bindings generator for rust (checksum custom derive)" ++documentation = "https://mozilla.github.io/uniffi-rs" ++homepage = "https://mozilla.github.io/uniffi-rs" ++repository = "https://github.com/mozilla/uniffi-rs" ++license = "MPL-2.0" ++edition = "2021" ++keywords = ["ffi", "bindgen"] ++ ++[lib] ++proc-macro = true ++ ++[dependencies] ++quote = "1.0" ++syn = { version = "1.0", features = ["derive"] } ++ ++[features] ++default = [] ++nightly = [] +diff --git a/uniffi_checksum_derive/src/lib.rs b/uniffi_checksum_derive/src/lib.rs +new file mode 100644 +index 000000000..c79064d8b +--- /dev/null ++++ b/uniffi_checksum_derive/src/lib.rs +@@ -0,0 +1,111 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++#![cfg_attr(feature = "nightly", feature(proc_macro_expand))] ++ ++//! Custom derive for uniffi_meta::Checksum ++ ++use proc_macro::TokenStream; ++use quote::{format_ident, quote}; ++use syn::{parse_macro_input, Data, DeriveInput, Fields, Index}; ++ ++#[proc_macro_derive(Checksum)] ++pub fn checksum_derive(input: TokenStream) -> TokenStream { ++ let input: DeriveInput = parse_macro_input!(input); ++ ++ let name = input.ident; ++ ++ let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); ++ ++ let code = match input.data { ++ Data::Enum(enum_) ++ if enum_.variants.len() == 1 ++ && enum_ ++ .variants ++ .iter() ++ .all(|variant| matches!(variant.fields, Fields::Unit)) => ++ { ++ quote!() ++ } ++ Data::Enum(enum_) => { ++ let match_inner = enum_.variants.iter().enumerate().map(|(num, variant)| { ++ let num = num as u64; ++ let ident = &variant.ident; ++ if variant.discriminant.is_some() { ++ panic!("#[derive(Checksum)] doesn't support explicit discriminants in enums"); ++ } ++ let discriminant = quote! { state.write(&#num.to_le_bytes()) }; ++ match &variant.fields { ++ Fields::Unnamed(fields) => { ++ let field_idents = fields ++ .unnamed ++ .iter() ++ .enumerate() ++ .map(|(num, _)| format_ident!("__self_{}", num)) ++ .collect::<Vec<_>>(); ++ let field_stmts = field_idents ++ .iter() ++ .map(|ident| quote! { Checksum::checksum(#ident, state); }); ++ quote! { ++ Self::#ident(#(#field_idents,)*) => { ++ #discriminant; ++ #(#field_stmts)* ++ } ++ } ++ } ++ Fields::Named(fields) => { ++ let field_idents = fields ++ .named ++ .iter() ++ .map(|field| field.ident.as_ref().unwrap()) ++ .collect::<Vec<_>>(); ++ let field_stmts = field_idents ++ .iter() ++ .map(|ident| quote! { Checksum::checksum(#ident, state); }); ++ quote! { ++ Self::#ident { #(#field_idents,)* } => { ++ #discriminant; ++ #(#field_stmts)* ++ } ++ } ++ } ++ Fields::Unit => quote! { Self::#ident => #discriminant, }, ++ } ++ }); ++ quote! { ++ match self { ++ #(#match_inner)* ++ } ++ } ++ } ++ Data::Struct(struct_) => { ++ let stmts = ++ struct_ ++ .fields ++ .iter() ++ .enumerate() ++ .map(|(num, field)| match field.ident.as_ref() { ++ Some(ident) => quote! { Checksum::checksum(&self.#ident, state); }, ++ None => { ++ let i = Index::from(num); ++ quote! { Checksum::checksum(&self.#i, state); } ++ } ++ }); ++ quote! { ++ #(#stmts)* ++ } ++ } ++ Data::Union(_) => { ++ panic!("#[derive(Checksum)] is not supported for unions"); ++ } ++ }; ++ ++ quote! { ++ impl #impl_generics Checksum for #name #ty_generics #where_clause { ++ fn checksum<__H: ::core::hash::Hasher>(&self, state: &mut __H) { ++ #code ++ } ++ } ++ } ++ .into() ++} +diff --git a/uniffi_meta/Cargo.toml b/uniffi_meta/Cargo.toml +index ca33156df..358b6ef4c 100644 +--- a/uniffi_meta/Cargo.toml ++++ b/uniffi_meta/Cargo.toml +@@ -10,3 +10,4 @@ keywords = ["ffi", "bindgen"] + + [dependencies] + serde = { version = "1.0.136", features = ["derive"] } ++uniffi_checksum_derive = { version = "0.21.0", path = "../uniffi_checksum_derive" } +diff --git a/uniffi_meta/src/lib.rs b/uniffi_meta/src/lib.rs +index 6cfa733e9..2555ae19c 100644 +--- a/uniffi_meta/src/lib.rs ++++ b/uniffi_meta/src/lib.rs +@@ -6,10 +6,79 @@ use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, + }; ++pub use uniffi_checksum_derive::Checksum; + + use serde::{Deserialize, Serialize}; + +-#[derive(Clone, Debug, Hash, Deserialize, Serialize)] ++pub trait Checksum { ++ fn checksum<H: Hasher>(&self, state: &mut H); ++} ++ ++impl Checksum for bool { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ Hash::hash(self, state); ++ } ++} ++ ++impl Checksum for u64 { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ state.write(&self.to_le_bytes()); ++ } ++} ++ ++impl Checksum for i64 { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ state.write(&self.to_le_bytes()); ++ } ++} ++ ++impl<T: Checksum> Checksum for Box<T> { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ (**self).checksum(state) ++ } ++} ++ ++impl<T: Checksum> Checksum for [T] { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ state.write(&(self.len() as u64).to_le_bytes()); ++ for item in self { ++ Checksum::checksum(item, state); ++ } ++ } ++} ++ ++impl<T: Checksum> Checksum for Vec<T> { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ Checksum::checksum(&**self, state); ++ } ++} ++ ++impl<T: Checksum> Checksum for Option<T> { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ match self { ++ None => state.write(&0u64.to_le_bytes()), ++ Some(value) => { ++ state.write(&1u64.to_le_bytes()); ++ Checksum::checksum(value, state) ++ } ++ } ++ } ++} ++ ++impl Checksum for str { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ state.write(self.as_bytes()); ++ state.write_u8(0xff); ++ } ++} ++ ++impl Checksum for String { ++ fn checksum<H: Hasher>(&self, state: &mut H) { ++ (**self).checksum(state) ++ } ++} ++ ++#[derive(Clone, Debug, Checksum, Deserialize, Serialize)] + pub struct FnMetadata { + pub module_path: Vec<String>, + pub name: String, +@@ -23,7 +92,7 @@ impl FnMetadata { + } + } + +-#[derive(Clone, Debug, Hash, Deserialize, Serialize)] ++#[derive(Clone, Debug, Checksum, Deserialize, Serialize)] + pub struct MethodMetadata { + pub module_path: Vec<String>, + pub self_name: String, +@@ -39,14 +108,14 @@ impl MethodMetadata { + } + } + +-#[derive(Clone, Debug, Hash, Deserialize, Serialize)] ++#[derive(Clone, Debug, Checksum, Deserialize, Serialize)] + pub struct FnParamMetadata { + pub name: String, + #[serde(rename = "type")] + pub ty: Type, + } + +-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)] ++#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Checksum, Deserialize, Serialize)] + pub enum Type { + U8, + U16, +@@ -78,21 +147,21 @@ pub enum Type { + }, + } + +-#[derive(Clone, Debug, Hash, Deserialize, Serialize)] ++#[derive(Clone, Debug, Checksum, Deserialize, Serialize)] + pub struct RecordMetadata { + pub module_path: Vec<String>, + pub name: String, + pub fields: Vec<FieldMetadata>, + } + +-#[derive(Clone, Debug, Hash, Deserialize, Serialize)] ++#[derive(Clone, Debug, Checksum, Deserialize, Serialize)] + pub struct FieldMetadata { + pub name: String, + #[serde(rename = "type")] + pub ty: Type, + } + +-#[derive(Clone, Debug, Hash, Deserialize, Serialize)] ++#[derive(Clone, Debug, Checksum, Deserialize, Serialize)] + pub struct ObjectMetadata { + pub module_path: Vec<String>, + pub name: String, +@@ -112,9 +181,9 @@ impl ObjectMetadata { + /// + /// To be used as a checksum of FFI symbols, as a safeguard against different UniFFI versions being + /// used for scaffolding and bindings generation. +-pub fn checksum<T: Hash>(val: &T) -> u16 { ++pub fn checksum<T: Checksum>(val: &T) -> u16 { + let mut hasher = DefaultHasher::new(); +- val.hash(&mut hasher); ++ val.checksum(&mut hasher); + (hasher.finish() & 0x000000000000FFFF) as u16 + } + +@@ -124,7 +193,7 @@ pub fn fn_ffi_symbol_name(mod_path: &[String], name: &str, checksum: u16) -> Str + } + + /// Enum covering all the possible metadata types +-#[derive(Clone, Debug, Hash, Deserialize, Serialize)] ++#[derive(Clone, Debug, Checksum, Deserialize, Serialize)] + pub enum Metadata { + Func(FnMetadata), + Method(MethodMetadata), |