fix: migrate off unsound serde_yml to serde_norway
serde_yml (RUSTSEC-2025-0068) and its libyml backend (RUSTSEC-2025-0067) are archived, unsound, and unmaintained with no patched version. Swap to serde_norway, the maintained serde_yaml fork on unsafe-libyaml-norway — a drop-in for our from_str / to_string / Value usage across persistence, undo, and the catalog parser. Clears both advisories (cargo audit / osv-scanner / grype all clean; serde_yml + libyml gone from the tree). No behaviour change; full suite 2151/0/1.
This commit is contained in:
Generated
+11
-17
@@ -908,16 +908,6 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libyml"
|
|
||||||
version = "0.0.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "line-clipping"
|
name = "line-clipping"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@@ -1545,7 +1535,7 @@ dependencies = [
|
|||||||
"ratatui",
|
"ratatui",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yml",
|
"serde_norway",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -1718,18 +1708,16 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_yml"
|
name = "serde_norway"
|
||||||
version = "0.0.12"
|
version = "0.9.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd"
|
checksum = "e408f29489b5fd500fab51ff1484fc859bb655f32c671f307dcd733b72e8168c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"itoa",
|
"itoa",
|
||||||
"libyml",
|
|
||||||
"memchr",
|
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
"version_check",
|
"unsafe-libyaml-norway",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2192,6 +2180,12 @@ version = "0.2.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unsafe-libyaml-norway"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b39abd59bf32521c7f2301b52d05a6a2c975b6003521cbd0c6dc1582f0a22104"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
|||||||
+4
-1
@@ -30,7 +30,10 @@ rand = "0.10.1"
|
|||||||
ratatui = "0.30.0"
|
ratatui = "0.30.0"
|
||||||
rusqlite = { version = "0.39.0", features = ["backup", "bundled", "column_metadata"] }
|
rusqlite = { version = "0.39.0", features = ["backup", "bundled", "column_metadata"] }
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
serde_yml = "0.0.12"
|
# Maintained fork of `serde_yaml` (the deprecated original). Replaces
|
||||||
|
# `serde_yml`, which was archived as unsound + unmaintained
|
||||||
|
# (RUSTSEC-2025-0068, and its `libyml` backend RUSTSEC-2025-0067).
|
||||||
|
serde_norway = "0.9.42"
|
||||||
sysinfo = { version = "0.39.0", default-features = false, features = ["system"] }
|
sysinfo = { version = "0.39.0", default-features = false, features = ["system"] }
|
||||||
tokio = { version = "1.52.2", features = ["full"] }
|
tokio = { version = "1.52.2", features = ["full"] }
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub struct Catalog {
|
|||||||
|
|
||||||
impl Catalog {
|
impl Catalog {
|
||||||
fn load() -> Self {
|
fn load() -> Self {
|
||||||
let value: serde_yml::Value = serde_yml::from_str(EN_US)
|
let value: serde_norway::Value = serde_norway::from_str(EN_US)
|
||||||
.expect("embedded en-US.yaml must parse (ADR-0019 §8.6 startup check)");
|
.expect("embedded en-US.yaml must parse (ADR-0019 §8.6 startup check)");
|
||||||
let mut entries = HashMap::new();
|
let mut entries = HashMap::new();
|
||||||
flatten(&value, String::new(), &mut entries);
|
flatten(&value, String::new(), &mut entries);
|
||||||
@@ -44,12 +44,12 @@ impl Catalog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flatten(
|
fn flatten(
|
||||||
value: &serde_yml::Value,
|
value: &serde_norway::Value,
|
||||||
prefix: String,
|
prefix: String,
|
||||||
out: &mut HashMap<String, String>,
|
out: &mut HashMap<String, String>,
|
||||||
) {
|
) {
|
||||||
match value {
|
match value {
|
||||||
serde_yml::Value::Mapping(map) => {
|
serde_norway::Value::Mapping(map) => {
|
||||||
for (k, v) in map {
|
for (k, v) in map {
|
||||||
let k_str = k
|
let k_str = k
|
||||||
.as_str()
|
.as_str()
|
||||||
@@ -62,14 +62,14 @@ fn flatten(
|
|||||||
flatten(v, next, out);
|
flatten(v, next, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serde_yml::Value::String(s) => {
|
serde_norway::Value::String(s) => {
|
||||||
out.insert(prefix, s.clone());
|
out.insert(prefix, s.clone());
|
||||||
}
|
}
|
||||||
// Empty top-level (Null) is fine — an empty catalog
|
// Empty top-level (Null) is fine — an empty catalog
|
||||||
// loads as no entries. Anything else is a structure
|
// loads as no entries. Anything else is a structure
|
||||||
// error worth panicking over since the catalog is
|
// error worth panicking over since the catalog is
|
||||||
// shipped with the binary.
|
// shipped with the binary.
|
||||||
serde_yml::Value::Null if prefix.is_empty() => {}
|
serde_norway::Value::Null if prefix.is_empty() => {}
|
||||||
other => panic!("catalog value at `{prefix}` is not a string: {other:?}"),
|
other => panic!("catalog value at `{prefix}` is not a string: {other:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ fn read_version(body: &str) -> Result<u32, MigrateError> {
|
|||||||
struct VersionOnly {
|
struct VersionOnly {
|
||||||
version: u32,
|
version: u32,
|
||||||
}
|
}
|
||||||
let v: VersionOnly = serde_yml::from_str(body).map_err(|e| {
|
let v: VersionOnly = serde_norway::from_str(body).map_err(|e| {
|
||||||
MigrateError::VersionParse(e.to_string())
|
MigrateError::VersionParse(e.to_string())
|
||||||
})?;
|
})?;
|
||||||
Ok(v.version)
|
Ok(v.version)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! `project.yaml` writer (hand-rolled, ADR-0015 §3) and
|
//! `project.yaml` writer (hand-rolled, ADR-0015 §3) and
|
||||||
//! reader (`serde_yml`, ADR-0015 §7).
|
//! reader (`serde_norway`, ADR-0015 §7).
|
||||||
//!
|
//!
|
||||||
//! The schema YAML uses a small, fixed set of structures —
|
//! The schema YAML uses a small, fixed set of structures —
|
||||||
//! tables, columns, relationships — and the values it carries
|
//! tables, columns, relationships — and the values it carries
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
//! the fixed `Type` enum, action names from `ReferentialAction`).
|
//! the fixed `Type` enum, action names from `ReferentialAction`).
|
||||||
//! Hand-rolling the writer avoids pulling a YAML serializer
|
//! Hand-rolling the writer avoids pulling a YAML serializer
|
||||||
//! dep just for the write path; the read path uses
|
//! dep just for the write path; the read path uses
|
||||||
//! `serde_yml` because we need to handle whatever the user
|
//! `serde_norway` because we need to handle whatever the user
|
||||||
//! (or a future migrator, or a hand-edit) puts in there.
|
//! (or a future migrator, or a hand-edit) puts in there.
|
||||||
//
|
//
|
||||||
// `pub(crate)` items in this private submodule are
|
// `pub(crate)` items in this private submodule are
|
||||||
@@ -268,7 +268,7 @@ const fn is_safe_yaml_char(c: char) -> bool {
|
|||||||
/// fatal banner per ADR-0015 §8.
|
/// fatal banner per ADR-0015 §8.
|
||||||
pub(crate) fn parse_schema(body: &str) -> Result<SchemaSnapshot, YamlError> {
|
pub(crate) fn parse_schema(body: &str) -> Result<SchemaSnapshot, YamlError> {
|
||||||
let raw: RawProject =
|
let raw: RawProject =
|
||||||
serde_yml::from_str(body).map_err(|e| YamlError::Syntax(e.to_string()))?;
|
serde_norway::from_str(body).map_err(|e| YamlError::Syntax(e.to_string()))?;
|
||||||
if raw.version != 1 {
|
if raw.version != 1 {
|
||||||
return Err(YamlError::UnsupportedVersion(raw.version));
|
return Err(YamlError::UnsupportedVersion(raw.version));
|
||||||
}
|
}
|
||||||
@@ -351,7 +351,7 @@ pub(crate) fn parse_schema(body: &str) -> Result<SchemaSnapshot, YamlError> {
|
|||||||
/// unparseable body for the same reason.
|
/// unparseable body for the same reason.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(super) fn parse_stored_mode(body: &str) -> Option<Mode> {
|
pub(super) fn parse_stored_mode(body: &str) -> Option<Mode> {
|
||||||
let raw: RawProject = serde_yml::from_str(body).ok()?;
|
let raw: RawProject = serde_norway::from_str(body).ok()?;
|
||||||
raw.project.mode.as_deref().and_then(Mode::from_keyword)
|
raw.project.mode.as_deref().and_then(Mode::from_keyword)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -412,7 +412,7 @@ impl SnapshotStore {
|
|||||||
let path = self.index_path();
|
let path = self.index_path();
|
||||||
let mut index = if path.exists() {
|
let mut index = if path.exists() {
|
||||||
let body = fs::read_to_string(&path).map_err(|e| io_err("read index", &path, e))?;
|
let body = fs::read_to_string(&path).map_err(|e| io_err("read index", &path, e))?;
|
||||||
serde_yml::from_str(&body).map_err(|e| SnapshotError::Index {
|
serde_norway::from_str(&body).map_err(|e| SnapshotError::Index {
|
||||||
message: e.to_string(),
|
message: e.to_string(),
|
||||||
})?
|
})?
|
||||||
} else {
|
} else {
|
||||||
@@ -437,7 +437,7 @@ impl SnapshotStore {
|
|||||||
|
|
||||||
fn save_index(&self, index: &Index) -> Result<()> {
|
fn save_index(&self, index: &Index) -> Result<()> {
|
||||||
create_dir_all(&self.root)?;
|
create_dir_all(&self.root)?;
|
||||||
let body = serde_yml::to_string(index).map_err(|e| SnapshotError::Index {
|
let body = serde_norway::to_string(index).map_err(|e| SnapshotError::Index {
|
||||||
message: e.to_string(),
|
message: e.to_string(),
|
||||||
})?;
|
})?;
|
||||||
let path = self.index_path();
|
let path = self.index_path();
|
||||||
|
|||||||
Reference in New Issue
Block a user