font-store: ignore malformed optional receipt values

This commit is contained in:
dotCooCoo committed 2026-11-03 12:16:28 -08:00
1 parent 8e6e369793
commit 600734ef54
2 files changed
+14 -2

No files matched your search

+13 -1
View File
@@ -126,10 +126,22 @@ struct Installed {
version: u32,
packs: Vec<InstalledLanguagePack>,
/// Committed backup IDs, recorded atomically with removing their pack entries.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[serde(default, deserialize_with = "read_receipts", skip_serializing_if = "Vec::is_empty")]
committed_removals: Vec<String>,
}
/// Decode optional receipt entries independently from the readable pack metadata. Record size
/// and JSON nesting remain bounded by the existing reader and serde_json's recursion limit.
fn read_receipts<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Vec<String>, D::Error> {
let entries = serde_json::Value::deserialize(deserializer)?;
Ok(match entries {
serde_json::Value::Array(entries) => {
entries.into_iter().filter_map(|entry| if let serde_json::Value::String(id) = entry { Some(id) } else { None }).collect()
}
_ => Vec::new(),
})
}
impl PackIndex {
/// Parses and checks an index: format 1, every locale a lowercase tag and listed once, every
/// archive at most [`MAX_PACK_ARCHIVE_BYTES`] with a sha256. Archive URLs must be `https://`
@@ -667,7 +667,7 @@ fn residual_one_bad_receipt_preserves_valid_metadata_and_cleanup() {
std::fs::create_dir_all(parent.join("11-12")).unwrap();
std::fs::write(parent.join("11-12/keep"), b"committed").unwrap();
let mut raw = serde_json::to_value(&original).unwrap();
raw["committed_removals"] = serde_json::json!(["11-12", "../outside"]);
raw["committed_removals"] = serde_json::json!(["11-12", "../outside", null, 42, true, {}, ["99-99"]]);
std::fs::write(store.dir().join(INSTALLED), serde_json::to_vec(&raw).unwrap()).unwrap();
let record = store.read_record().expect("one invalid receipt must not invalidate the whole record");
assert_eq!(record.committed_removals, ["11-12"]);