Skip to content

get_maximum_output_size overflows on 32-bit targets (wasm32) #204

@dglittle

Description

@dglittle

Bug

get_maximum_output_size computes:

16 + 4 + (input_len * 110 / 100)

On 32-bit targets (e.g. wasm32 where usize is u32), input_len * 110 overflows when input_len > 2^32 / 110 ≈ 39MB. This causes the function to return a much smaller value than expected.

For example, with input_len = 40_000_000:

  • Expected: 44_000_020
  • Actual (wasm32): 1_050_347 (after overflow wrapping)

This causes compress_into to receive an undersized output buffer, leading to a panic when compressing incompressible data larger than ~39MB.

Minimal reproduction

// Simulating wasm32 (u32) arithmetic:
let input_len: u32 = 40_000_000;
let result = 16 + 4 + (input_len.wrapping_mul(110) / 100);
// result = 1_050_347 (wrong, should be 44_000_020)

In practice, this crashes when using diamond-types (CRDT library) compiled to wasm32, which calls compress_into with a buffer allocated via get_maximum_output_size. A document with ~39MB+ of accumulated text content triggers the overflow.

Fix

Rearrange the arithmetic to avoid the intermediate overflow:

16 + 4 + input_len + input_len / 100 * 10 + input_len % 100 * 10 / 100

This produces identical results for all inputs but never computes input_len * 110.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions