synth_frontend/
validator.rs1use synth_core::{Component, Error, Result};
4
5pub struct ComponentValidator;
7
8impl ComponentValidator {
9 pub fn new() -> Self {
11 Self
12 }
13
14 pub fn validate(&self, component: &Component) -> Result<()> {
16 if component.modules.is_empty() {
20 return Err(Error::validation("Component must have at least one module"));
21 }
22
23 let total_memory = component.total_memory_size();
25 if total_memory == 0 {
26 tracing::warn!("Component has no linear memory");
27 }
28
29 const MAX_MEMORY_32BIT: u64 = 4 * 1024 * 1024 * 1024; if total_memory > MAX_MEMORY_32BIT {
32 return Err(Error::validation(format!(
33 "Total memory ({} bytes) exceeds 32-bit limit",
34 total_memory
35 )));
36 }
37
38 for module in &component.modules {
40 self.validate_module(module)?;
41 }
42
43 Ok(())
44 }
45
46 fn validate_module(&self, module: &synth_core::CoreModule) -> Result<()> {
48 if module.binary.is_empty() {
50 return Err(Error::validation("Module has empty binary"));
51 }
52
53 if module.binary.len() < 8 {
55 return Err(Error::validation("Module binary too short"));
56 }
57
58 let magic = &module.binary[0..4];
59 if magic != b"\x00asm" {
60 return Err(Error::validation("Invalid WebAssembly magic number"));
61 }
62
63 for memory in &module.memories {
65 if let Some(max) = memory.maximum
67 && memory.initial > max
68 {
69 return Err(Error::validation(format!(
70 "Memory initial size ({}) exceeds maximum ({})",
71 memory.initial, max
72 )));
73 }
74
75 const MAX_PAGES_32BIT: u32 = 65536;
77 if memory.initial > MAX_PAGES_32BIT {
78 return Err(Error::validation(format!(
79 "Memory initial size ({} pages) exceeds 32-bit limit",
80 memory.initial
81 )));
82 }
83 }
84
85 Ok(())
86 }
87}
88
89impl Default for ComponentValidator {
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use synth_core::{Component, CoreModule};
99
100 #[test]
101 fn test_validate_empty_component() {
102 let component = Component::new("test".to_string());
103 let validator = ComponentValidator::new();
104
105 let result = validator.validate(&component);
106 assert!(result.is_err()); }
108
109 #[test]
110 fn test_validate_valid_component() {
111 let mut component = Component::new("test".to_string());
112
113 let module = CoreModule {
115 id: "module0".to_string(),
116 binary: vec![0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00],
117 functions: Vec::new(),
118 memories: Vec::new(),
119 tables: Vec::new(),
120 globals: Vec::new(),
121 };
122 component.modules.push(module);
123
124 let validator = ComponentValidator::new();
125 let result = validator.validate(&component);
126 assert!(result.is_ok());
127 }
128}