Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration

libmagic-rs provides a single configuration struct, EvaluationConfig, that controls how magic rules are evaluated. All fields have safe defaults, and the validate() method enforces security bounds before any evaluation begins.

EvaluationConfig

#![allow(unused)]
fn main() {
use libmagic_rs::EvaluationConfig;

pub struct EvaluationConfig {
    pub max_recursion_depth: u32,       // Default: 20, max: 1000
    pub max_string_length: usize,       // Default: 8192, max: 1MB (1_048_576)
    pub stop_at_first_match: bool,      // Default: true
    pub enable_mime_types: bool,         // Default: false
    pub timeout_ms: Option<u64>,        // Default: None, max: 300_000 (5 min)
}
}

Field Reference

FieldTypeDefaultBoundsPurpose
max_recursion_depthu32201 – 1000Limits nested rule traversal depth to prevent stack overflow
max_string_lengthusize81921 – 1_048_576Caps bytes read for string types to prevent memory exhaustion
stop_at_first_matchbooltrueWhen true, evaluation stops after the first matching rule
enable_mime_typesboolfalseWhen true, maps file type descriptions to standard MIME types
timeout_msOption<u64>None1 – 300_000Per-file evaluation timeout in milliseconds; None disables

Constructor Presets

EvaluationConfig::new() / EvaluationConfig::default()

Returns balanced defaults suitable for most workloads:

#![allow(unused)]
fn main() {
let config = EvaluationConfig::new();

assert_eq!(config.max_recursion_depth, 20);
assert_eq!(config.max_string_length, 8192);
assert!(config.stop_at_first_match);
assert!(!config.enable_mime_types);
assert_eq!(config.timeout_ms, None);
}

EvaluationConfig::performance()

Optimized for high-throughput scenarios where speed matters more than completeness:

#![allow(unused)]
fn main() {
let config = EvaluationConfig::performance();

assert_eq!(config.max_recursion_depth, 10);
assert_eq!(config.max_string_length, 1024);
assert!(config.stop_at_first_match);
assert!(!config.enable_mime_types);
assert_eq!(config.timeout_ms, Some(1000)); // 1 second
}

EvaluationConfig::comprehensive()

Finds all matches with deep analysis, MIME type mapping, and a generous timeout:

#![allow(unused)]
fn main() {
let config = EvaluationConfig::comprehensive();

assert_eq!(config.max_recursion_depth, 50);
assert_eq!(config.max_string_length, 32768);
assert!(!config.stop_at_first_match);
assert!(config.enable_mime_types);
assert_eq!(config.timeout_ms, Some(30000)); // 30 seconds
}

Custom Configuration

Use struct update syntax to override individual fields from any preset:

#![allow(unused)]
fn main() {
use libmagic_rs::EvaluationConfig;

let config = EvaluationConfig {
    max_recursion_depth: 30,
    enable_mime_types: true,
    timeout_ms: Some(5000),
    ..EvaluationConfig::default()
};
}

Validation

Call validate() to check that all values fall within safe bounds. The MagicDatabase constructors call validate() automatically, so you only need to call it explicitly when creating a config that will be stored for later use.

#![allow(unused)]
fn main() {
use libmagic_rs::EvaluationConfig;

let config = EvaluationConfig::default();
assert!(config.validate().is_ok());

let bad = EvaluationConfig {
    max_recursion_depth: 0,
    ..EvaluationConfig::default()
};
assert!(bad.validate().is_err());
}

Validation Rules

The validate() method enforces four categories of security constraints:

Recursion depth – must be between 1 and 1000. A value of 0 is rejected because evaluation cannot proceed without at least one level. Values above 1000 risk stack overflow.

String length – must be between 1 and 1_048_576 (1 MB). A value of 0 is rejected because no string matching could occur. Values above 1 MB risk memory exhaustion.

Timeout – if Some, must be between 1 and 300_000 (5 minutes). A value of 0 is rejected as meaningless. Values above 5 minutes risk denial-of-service. None (no timeout) is always accepted.

Resource combination – a recursion depth above 100 combined with a string length above 65_536 is rejected. Deep recursion with large string reads at every level can compound into excessive resource consumption even when each value individually falls within safe bounds.

Using Configuration with MagicDatabase

Built-in Rules with Default Config

#![allow(unused)]
fn main() {
use libmagic_rs::MagicDatabase;

let db = MagicDatabase::with_builtin_rules()?;
let result = db.evaluate_buffer(b"\x7fELF")?;
}

Built-in Rules with Custom Config

#![allow(unused)]
fn main() {
use libmagic_rs::{MagicDatabase, EvaluationConfig};

let config = EvaluationConfig {
    timeout_ms: Some(5000),
    ..EvaluationConfig::default()
};
let db = MagicDatabase::with_builtin_rules_and_config(config)?;
}

Magic File with Custom Config

#![allow(unused)]
fn main() {
use libmagic_rs::{MagicDatabase, EvaluationConfig};

let config = EvaluationConfig::performance();
let db = MagicDatabase::load_from_file_with_config("custom.magic", config)?;
}

All three constructors call config.validate() internally and return an error if the configuration is invalid. There is no way to create a MagicDatabase with an invalid configuration.

CLI Usage

The command-line interface exposes the timeout_ms field via the --timeout-ms flag. All other configuration values use their defaults when running from the CLI.

# No timeout (default)
libmagic-rs sample.bin

# 5-second timeout per file
libmagic-rs --timeout-ms 5000 sample.bin

If evaluation exceeds the timeout, the file is skipped and an error message is printed to stderr with exit code 5.

Choosing a Preset

ScenarioPresetWhy
General file identificationdefault()Balanced depth and limits
Batch processing many filesperformance()Low limits, 1s timeout, early exit
Forensic analysiscomprehensive()Deep traversal, all matches, MIME types
Untrusted inputperformance()Tight bounds reduce attack surface
Custom requirementsStruct update syntaxOverride specific fields from any preset