vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
#![allow(clippy::expect_used)]
//! Catalog entry for `detect_hex_run`.

use crate::ops::security_detection::detector_support::{spans, DetectionError};

/// Embedded operation spec formerly stored in metadata/spec.toml.
pub const SPEC_TOML: &str = r#"schema_version = 1
id = "security_detection.detect_hex_run"
archetype = "match-bytes-pattern"
display_name = "Detect Hex Run"
summary = "Returns offsets of hexadecimal byte runs using a config-encoded minimum length."
category = "C"

[intrinsic]
wgsl = "security_detection_detect_hex_run"

[signature]
inputs = ["Bytes", "Bytes"]
output = "Bytes"

laws = []
equivalence_classes = ["long_run", "short_run", "mixed_case", "t47_cap"]
workgroup_size = [64, 1, 1]
tags = ["security-detection", "hex", "secret-scan", "t47"]
fixtures_dir = "fixtures/"
"#;

/// Embedded reference vectors formerly stored in fixtures/reference-vectors.toml.
pub const REFERENCE_VECTORS_TOML: &str = r#"[[case]]
name = "positive_digest"
input = "sha256=0123456789abcdefABCDEF"
min_run_len = 16
expected_offsets = [7]

[[case]]
name = "negative_short_hex"
input = "color #fff is not a secret"
min_run_len = 8
expected_offsets = []
"#;

/// WGSL lowering source for this detector.
pub mod lowering {
    /// Return the detector-specific WGSL source.
    #[must_use]
    pub const fn source() -> &'static str {
        r#"struct Params {
    input_len: u32,
    min_run_len: u32,
    max_offsets: u32,
    _pad0: u32,
}

struct OffsetOutput {
    count: atomic<u32>,
    data: array<u32>,
}

@group(0) @binding(0) var<storage, read> input: array<u32>;
@group(0) @binding(1) var<storage, read_write> output: OffsetOutput;
@group(0) @binding(2) var<uniform> params: Params;

fn is_hex(byte: u32) -> bool {
    let numeric = byte >= 48u && byte <= 57u;
    let upper = byte >= 65u && byte <= 70u;
    let lower = byte >= 97u && byte <= 102u;
    return numeric || upper || lower;
}

fn is_start(index: u32) -> bool {
    if (index >= params.input_len || !is_hex(input[index])) {
        return false;
    }
    if (index == 0u) {
        return true;
    }
    return !is_hex(input[index - 1u]);
}

fn run_end(start: u32) -> u32 {
    var end = start;
    loop {
        if (end >= params.input_len || !is_hex(input[end])) {
            break;
        }
        end = end + 1u;
    }
    return end;
}

fn emit_offset(offset: u32) {
    let slot = atomicAdd(&output.count, 1u);
    if (slot < params.max_offsets) {
        output.data[slot] = offset;
    }
}

@compute @workgroup_size(64)
fn security_detection_detect_hex_run(@builtin(global_invocation_id) gid: vec3<u32>) {
    let start = gid.x;
    if (params.min_run_len == 0u || !is_start(start)) {
        return;
    }
    let end = run_end(start);
    if (end - start >= params.min_run_len) {
        emit_offset(start);
    }
}
"#
    }
}

/// Return offsets of hexadecimal byte runs using a minimum length.
///
/// # Errors
///
/// Returns `Fix: ...` when input exceeds 64 MiB or offsets exceed the ABI.
pub fn detect_hex_run(input: &[u8], min_run_len: u32) -> Result<Vec<u32>, DetectionError> {
    spans::hex_run_offsets(input, min_run_len)
}

/// Parsed hex run configuration.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DetectHexRunConfig {
    /// Minimum accepted run length.
    pub min_run_len: u32,
}

/// Decode the hex run detector config from little-endian bytes.
///
/// # Errors
///
/// Returns `Fix: ...` when the config buffer is shorter than four bytes.
pub fn detect_hex_run_config(config: &[u8]) -> Result<DetectHexRunConfig, DetectionError> {
    let bytes: [u8; 4] = config
        .get(..4)
        .ok_or_else(|| "Fix: provide at least 4 config bytes for min_run_len".to_string())?
        .try_into()
        .expect("slice length checked");
    Ok(DetectHexRunConfig {
        min_run_len: u32::from_le_bytes(bytes),
    })
}

/// Compatibility surface for the previous generated implementation module.
pub mod implementation {
    pub use super::detect_hex_run;
    pub use super::{detect_hex_run_config, DetectHexRunConfig};
    /// Compatibility module for callers that used the generated kernel path.
    pub mod kernel {
        pub use super::super::{detect_hex_run, detect_hex_run_config, DetectHexRunConfig};
    }

    /// Compatibility module for callers that used the generated lowering path.
    pub mod lowering {
        /// Compatibility module for callers that used `implementation::lowering::wgsl`.
        pub mod wgsl {
            pub use super::super::super::lowering::source;
        }
    }
}