Problem:
#5905 changed XDRDecoder.ReadFrom from the streaming xdr.Unmarshal to the buffered xdr.SafeUnmarshal to address a DoS vulnerability where the InputLen() guard could be bypassed by streaming readers.
However, this change introduces a different risk: unbounded memory allocation. The implementation now reads the entire decompressed payload into memory using io.ReadAll() with no size limit.
Proposed Fix:
Introduce size limits to prevent unbounded allocations:
- Apply an io.LimitReader to decompressed data in XDRDecoder.ReadFrom
- Apply an io.LimitReader to compressed object downloads in ledger_buffer.downloadLedgerObject
To keep this flexible for different deployments, these limits could be:
- Exposed as configurable constants in the compressxdr package, or optionally configurable via fields on XDRDecoder
- The exact limits can be chosen based on expected ledger object sizes and memory constraints, while taking into account the additional memory usage from parallel downloads and buffering.
Problem:
#5905 changed XDRDecoder.ReadFrom from the streaming xdr.Unmarshal to the buffered xdr.SafeUnmarshal to address a DoS vulnerability where the InputLen() guard could be bypassed by streaming readers.
However, this change introduces a different risk: unbounded memory allocation. The implementation now reads the entire decompressed payload into memory using io.ReadAll() with no size limit.
Proposed Fix:
Introduce size limits to prevent unbounded allocations:
To keep this flexible for different deployments, these limits could be: