use vyre::ir::Program;
use vyre_primitives::graph::program_graph::ProgramGraphShape;
use vyre_primitives::predicate::edge_kind;
#[cfg(test)]
use crate::security::flow_composition::sanitized_dataflow_hit_cpu_ref;
use crate::security::flow_composition::sanitized_dataflow_hit_program;
pub(crate) const OP_ID: &str = "vyre-libs::security::flows_to_with_sanitizer";
#[must_use]
pub fn flows_to_with_sanitizer(
shape: ProgramGraphShape,
source_buf: &str,
sink_buf: &str,
sanitizer_buf: &str,
clean_buf: &str,
reach_buf: &str,
alive_buf: &str,
hits_buf: &str,
out_scalar_buf: &str,
) -> Program {
sanitized_dataflow_hit_program(
OP_ID,
shape,
source_buf,
sink_buf,
sanitizer_buf,
clean_buf,
reach_buf,
alive_buf,
hits_buf,
out_scalar_buf,
)
}
#[must_use]
#[cfg(test)]
pub(crate) fn cpu_ref(
node_count: u32,
edge_offsets: &[u32],
edge_targets: &[u32],
edge_kind_mask: &[u32],
source: &[u32],
sink: &[u32],
sanitizer: &[u32],
) -> u32 {
sanitized_dataflow_hit_cpu_ref(
node_count,
edge_offsets,
edge_targets,
edge_kind_mask,
source,
sink,
sanitizer,
)
}
inventory::submit! {
crate::harness::OpEntry {
id: OP_ID,
build: || flows_to_with_sanitizer(ProgramGraphShape::new(4, 3), "source", "sink", "sanitizer", "clean", "reach", "alive", "hits", "out_scalar"),
test_inputs: Some(|| {
let to_bytes = vyre_primitives::wire::pack_u32_slice;
vec![vec![
to_bytes(&[0b0001]), to_bytes(&[0b0000]), to_bytes(&[0b0001]), to_bytes(&[0, 0, 0, 0]), to_bytes(&[0, 1, 2, 3, 3]), to_bytes(&[1, 2, 3]), to_bytes(&[
edge_kind::ASSIGNMENT,
edge_kind::ASSIGNMENT,
edge_kind::ASSIGNMENT,
]), to_bytes(&[0, 0, 0, 0]), to_bytes(&[0b0001]), to_bytes(&[0b0000]), to_bytes(&[0b0010]), to_bytes(&[0b0000]), to_bytes(&[0b0000]), ]]
}),
expected_output: Some(|| {
let to_bytes = vyre_primitives::wire::pack_u32_slice;
vec![vec![
to_bytes(&[0b0001]), to_bytes(&[0b0011]), to_bytes(&[0b0011]), to_bytes(&[0b0010]), to_bytes(&[0b0001]), ]]
}),
category: Some("security"),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::security::flow_composition::linear_dataflow;
#[test]
fn unsanitized_source_reaches_sink_returns_one() {
let (off, tgt, msk) = linear_dataflow(4);
let result = cpu_ref(4, &off, &tgt, &msk, &[0b0001], &[0b0010], &[0]);
assert_eq!(result, 1);
}
#[test]
fn source_killed_by_sanitizer_returns_zero() {
let (off, tgt, msk) = linear_dataflow(4);
let result = cpu_ref(4, &off, &tgt, &msk, &[0b0001], &[0b0010], &[0b0001]);
assert_eq!(result, 0);
}
#[test]
fn landing_killed_by_sanitizer_returns_zero() {
let (off, tgt, msk) = linear_dataflow(4);
let result = cpu_ref(4, &off, &tgt, &msk, &[0b0001], &[0b0010], &[0b0010]);
assert_eq!(result, 0);
}
#[test]
fn unrelated_sanitizer_passes_through() {
let (off, tgt, msk) = linear_dataflow(4);
let result = cpu_ref(4, &off, &tgt, &msk, &[0b0001], &[0b0010], &[0b1000]);
assert_eq!(result, 1);
}
#[test]
fn empty_source_returns_zero() {
let (off, tgt, msk) = linear_dataflow(4);
let result = cpu_ref(4, &off, &tgt, &msk, &[0], &[0b0010], &[0]);
assert_eq!(result, 0);
}
#[test]
fn empty_sink_returns_zero() {
let (off, tgt, msk) = linear_dataflow(4);
let result = cpu_ref(4, &off, &tgt, &msk, &[0b0001], &[0], &[0]);
assert_eq!(result, 0);
}
}