-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement serialization protection via magic (#169)
## What Changed? This adds a u64 magic number to the beginning of the output artifact from `paralegal-flow` which is verified upon loading the artifact. The magic number is a hash of the modification dates of all files in the `paralegal-spdg` crate. ## Why Does It Need To? At present there is no protection that the format expected by a policy application conforms to the format written by the flow analyzer. Specifically the analyzer may be compiled against an older or newer version of `paralegal-spdg`. In such cases the derived `serde` implementation for the output artifact may differ. `bincode`, the serialization library we use, does not offer protection against this case, leading to out-of-memory errors and memory leaks in deserialization. The magic hash added detects this version mismatch and reports it. ## Checklist - [x] Above description has been filled out so that upon quash merge we have a good record of what changed. - [x] New functions, methods, types are documented. Old documentation is updated if necessary - [ ] Documentation in Notion has been updated - [ ] Tests for new behaviors are provided - [ ] New test suites (if any) ave been added to the CI tests (in `.github/workflows/rust.yml`) either as compiler test or integration test. *Or* justification for their omission from CI has been provided in this PR description.
- Loading branch information
1 parent
c52fc5c
commit 52a64bd
Showing
3 changed files
with
97 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
use anyhow::Context; | ||
use anyhow::Result; | ||
use std::collections::hash_map::DefaultHasher; | ||
use std::env; | ||
use std::fs; | ||
use std::hash::{Hash, Hasher}; | ||
use std::path::{Path, PathBuf}; | ||
use std::time::SystemTime; | ||
|
||
fn rustup_toolchain_path() -> PathBuf { | ||
let rustup_home = env::var("RUSTUP_HOME").unwrap(); | ||
let rustup_tc = env::var("RUSTUP_TOOLCHAIN").unwrap(); | ||
[&rustup_home, "toolchains", &rustup_tc] | ||
.into_iter() | ||
.collect() | ||
} | ||
|
||
fn get_rustup_lib_path() -> PathBuf { | ||
let mut rustup_lib = rustup_toolchain_path(); | ||
rustup_lib.push("lib"); | ||
rustup_lib | ||
} | ||
|
||
/// Helper for calculating a hash of all (modification dates of) Rust files in this crate. | ||
fn visit_dirs(dir: &Path, hasher: &mut DefaultHasher) -> Result<()> { | ||
if !dir.is_dir() { | ||
return Ok(()); | ||
} | ||
for entry in fs::read_dir(dir)? { | ||
let entry = entry?; | ||
let path = entry.path(); | ||
if path.is_dir() { | ||
visit_dirs(&path, hasher)?; | ||
} else if path.extension().map_or(false, |ext| ext == "rs") { | ||
let metadata = entry.metadata()?; | ||
let modified = metadata.modified()?; | ||
|
||
let duration = modified.duration_since(SystemTime::UNIX_EPOCH)?; | ||
duration.as_secs().hash(hasher); | ||
// Tell Cargo to rerun if this source file changes | ||
println!("cargo:rerun-if-changed={}", path.display()); | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
/// Calculate a hash of all (modification dates of) Rust files in this crate. | ||
fn calculate_source_hash() -> u64 { | ||
let mut hasher = DefaultHasher::new(); | ||
|
||
// Start from the src directory | ||
visit_dirs(Path::new("src"), &mut hasher) | ||
.with_context(|| "Calculating source hash") | ||
.unwrap(); | ||
|
||
hasher.finish() | ||
} | ||
|
||
fn main() { | ||
let magic = calculate_source_hash(); | ||
|
||
// Emit the hash as an environment variable | ||
println!("cargo:rustc-env=SER_MAGIC={:0}", magic); | ||
|
||
// Original linux-specific code | ||
if cfg!(target_os = "linux") { | ||
let rustup_lib = get_rustup_lib_path(); | ||
println!("cargo:rustc-link-search=native={}", rustup_lib.display()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters