Category: Code Maturity
Incomplete WebAssembly table-section validation
Informational Severity
Informational Impact
Low Likelihood
Description
The WebAssembly module validator checks the initial size of tables against a configured maximum but does not check the table's specified maximum size limit,
pub fn enforce_table_limit(self, max_initial_table_size: u32) -> Result<Self, PrepareError> {
let section = self.module.table_section()?;
if let Some(section) = section {
if section.len() > 1 {
return Err(PrepareError::InvalidTable(InvalidTable::MoreThanOneTable));
}
if let Some(table) = section.get(0) {
if table.ty.initial > max_initial_table_size {
return Err(PrepareError::InvalidTable(
InvalidTable::InitialTableSizeLimitExceeded,
));
}
// Note: table.ty.maximum is not checked
}
}
Ok(self)
}
while memory sections properly validate both initial and maximum size limits:
if let Some(max) = memory.maximum {
if max > max_memory_size_in_pages.into() {
return Err(PrepareError::InvalidMemory(
InvalidMemory::MemorySizeLimitExceeded,
));
}
}
Impact
Currently, this is not exploitable because the implementation uses a WebAssembly MVP target that does not support table growth, and relevant instructions like table.grow
are disabled in the wasmparser
configuration as GC proposal support is not enabled.
Recommendations
To maintain consistency with memory validation and future-proof the codebase, we recommend the following validation for table sections:
pub fn enforce_table_limit(self, max_table_size: u32) -> Result<Self, PrepareError> {
let section = self.module.table_section()?;
if let Some(section) = section {
if section.len() > 1 {
return Err(PrepareError::InvalidTable(InvalidTable::MoreThanOneTable));
}
if let Some(table) = section.get(0) {
// Check initial size
if table.ty.initial > max_table_size {
return Err(PrepareError::InvalidTable(
InvalidTable::InitialTableSizeLimitExceeded,
));
}
// Check maximum size if specified
if let Some(max) = table.ty.maximum {
if max > max_table_size {
return Err(PrepareError::InvalidTable(
InvalidTable::MaximumTableSizeLimitExceeded,
));
}
}
}
}
Ok(self)
}