From df1b7d1d817d07772073a8ee35dc1d83b6872047 Mon Sep 17 00:00:00 2001 From: Marybeth Fair Date: Fri, 30 Aug 2024 15:37:27 +0000 Subject: [PATCH] Add a function to fingerprint flag/offset info. Uses SipHasher implementation added to the project. Ideally the output would remain consistent between builds (though the worst case of an updated algorithm would be a string lookup for cross-container reads only). Sort the flags first so everything is always added to the hasher in the same order - note this code is only run at build time, not runtime. Next step is to write this fingerprint into the package.map file and introduce a flag to guard this change. Bug: 316357686 Test: atest aconfig.test Change-Id: Ie5f34541d982dfa120ffb05fc0790603689d47c0 --- tools/aconfig/aconfig/src/commands.rs | 35 ++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs index 59f06627ee..1a14f6415a 100644 --- a/tools/aconfig/aconfig/src/commands.rs +++ b/tools/aconfig/aconfig/src/commands.rs @@ -17,7 +17,8 @@ use anyhow::{bail, ensure, Context, Result}; use itertools::Itertools; use protobuf::Message; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; +use std::hash::Hasher; use std::io::Read; use std::path::PathBuf; @@ -31,6 +32,7 @@ use aconfig_protos::{ ParsedFlagExt, ProtoFlagMetadata, ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag, ProtoParsedFlags, ProtoTracepoint, }; +use aconfig_storage_file::sip_hasher13::SipHasher13; use aconfig_storage_file::StorageFileType; pub struct Input { @@ -410,11 +412,42 @@ where Ok(flag_ids) } +#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to + // protect hardcoded offset reads. +pub fn compute_flag_offsets_fingerprint(flags_map: &HashMap) -> Result { + let mut hasher = SipHasher13::new(); + + // Need to sort to ensure the data is added to the hasher in the same order + // each run. + let sorted_map: BTreeMap<&String, &u16> = flags_map.iter().collect(); + + for (flag, offset) in sorted_map { + // See https://docs.rs/siphasher/latest/siphasher/#note for use of write + // over write_i16. Similarly, use to_be_bytes rather than to_ne_bytes to + // ensure consistency. + hasher.write(flag.as_bytes()); + hasher.write(&offset.to_be_bytes()); + } + Ok(hasher.finish()) +} + #[cfg(test)] mod tests { use super::*; use aconfig_protos::ProtoFlagPurpose; + #[test] + fn test_offset_fingerprint() { + let parsed_flags = crate::test::parse_test_flags(); + let package = find_unique_package(&parsed_flags.parsed_flag).unwrap().to_string(); + let flag_ids = assign_flag_ids(&package, parsed_flags.parsed_flag.iter()).unwrap(); + let expected_fingerprint = 10709892481002252132u64; + + let hash_result = compute_flag_offsets_fingerprint(&flag_ids); + + assert_eq!(hash_result.unwrap(), expected_fingerprint); + } + #[test] fn test_parse_flags() { let parsed_flags = crate::test::parse_test_flags(); // calls parse_flags