Assessment reports>Radix>Informational findings>Incomplete WebAssembly table-section validation
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)
}

Remediation

Zellic © 2025Back to top ↑