Skip to content

Graceful Handling of OOM in table.grow #5394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

charmitro
Copy link
Contributor

@charmitro charmitro commented Feb 15, 2025

Introduce DEFAULT_MAX_TABLE_SIZE set to 1,048,576 elements (~1
million, 2^20) as a default cap for tables lacking a specified
maximum (self.maximum = None). This prevents impractical growth
attempts, such as a delta of 0xff_ff_ff_ff (4,294,967,295 elements),
which could succeed misleadingly on overcommitting systems like macOS.

Replace panic-prone Vec::resize with try_reserve_exact to attempt
memory reservation before resizing. Returns None (mapping to
WebAssembly’s -1) on allocation failure, ensuring graceful handling of
out-of-memory (OOM) conditions rather than crashing, as seen
previously on Linux with large deltas.

Update growth logic to compute the effective
maximum (self.maximum.unwrap_or(DEFAULT_MAX_TABLE_SIZE)), failing
early if new_len exceeds this limit, followed by a safe reservation
and resize sequence.

These changes align with the WebAssembly 2.0 (Draft 2025-01-28) spec’s
allowance for implementation-defined resource limits (Section 7.2) and
table.grow semantics (returning -1 on exceeding limits or resource
constraints).

@charmitro charmitro force-pushed the table-grow-max branch 2 times, most recently from 080a2be to 532b0a9 Compare February 21, 2025 22:54
This commit enhances the `VMTable::grow` method to impose a uniform
failure condition for extreme table growth requests, addressing
platform-specific discrepancies observed in prior
implementations (e.g., Linux returning -1 due to strict allocation
limits, macOS returning 0 due to virtual memory overcommitment).

Introduce `DEFAULT_MAX_TABLE_SIZE` set to 1,048,576 elements (~1
million, 2^20) as a default cap for tables lacking a specified
maximum (`self.maximum = None`). This prevents impractical growth
attempts, such as a delta of 0xff_ff_ff_ff (4,294,967,295 elements),
which could succeed misleadingly on overcommitting systems like macOS.

Replace panic-prone `Vec::resize` with `try_reserve_exact` to attempt
memory reservation before resizing. Returns `None` (mapping to
WebAssembly’s -1) on allocation failure, ensuring graceful handling of
out-of-memory (OOM) conditions rather than crashing, as seen
previously on Linux with large deltas.

Update growth logic to compute the effective
maximum (`self.maximum.unwrap_or(DEFAULT_MAX_TABLE_SIZE)`), failing
early if `new_len` exceeds this limit, followed by a safe reservation
and resize sequence.

These changes align with the WebAssembly 2.0 (Draft 2025-01-28) spec’s
allowance for implementation-defined resource limits (Section 7.2) and
`table.grow` semantics (returning -1 on exceeding limits or resource
constraints).

Signed-off-by: Charalampos Mitrodimas <[email protected]>
Adds a new test to verify table.grow behavior with very large
delta (0xff_ff_ff_ff).

Signed-off-by: Charalampos Mitrodimas <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants