Skip to content
Permalink
Browse files
Compression Streams Handle Out of Memory Conditions
https://bugs.webkit.org/show_bug.cgi?id=244411

Reviewed by Youenn Fablet.

Compression Streams scales up memory quite quickly, and can exhaust memory on
a lower spec device. This patch will scale down memory usage if allocations start failing.

A guard limit of 16KB of free memory was added. If free memory falls below that limit we will give up and
report to the stream not enough memory is avaiable to continue.

* Source/WebCore/Modules/compression/CompressionStreamEncoder.cpp:
(WebCore::CompressionStreamEncoder::compress):
* Source/WebCore/Modules/compression/DecompressionStreamDecoder.cpp:
(WebCore::DecompressionStreamDecoder::decompressZlib):
(WebCore::DecompressionStreamDecoder::decompressAppleCompressionFramework):

Canonical link: https://commits.webkit.org/253930@main
  • Loading branch information
stwrt committed Aug 30, 2022
1 parent bc90c50 commit 7a01e745839ab2ac19fe60d0b619034a2339a6cf
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
@@ -98,7 +98,7 @@ ExceptionOr<bool> CompressionStreamEncoder::initialize()
ExceptionOr<RefPtr<JSC::ArrayBuffer>> CompressionStreamEncoder::compress(const uint8_t* input, const size_t inputLength)
{

size_t allocateSize = startingAllocationSize;
size_t allocateSize = (inputLength < startingAllocationSize) ? startingAllocationSize : inputLength;
auto storage = SharedBufferBuilder();

int result;
@@ -114,7 +114,17 @@ ExceptionOr<RefPtr<JSC::ArrayBuffer>> CompressionStreamEncoder::compress(const u
}

while (shouldCompress) {
auto output = Vector<uint8_t>(allocateSize);
auto output = Vector<uint8_t>();

This comment has been minimized.

Copy link
@saambarati

saambarati Aug 30, 2022

Contributor

Why not just Vector<uint8_t> output;?

This comment has been minimized.

Copy link
@saambarati

saambarati Aug 30, 2022

Contributor

ditto for the other use cases

if (!output.tryReserveInitialCapacity(allocateSize)) {
allocateSize /= 4;

if (allocateSize < startingAllocationSize)
return Exception { OutOfMemoryError };

continue;
}

output.resize(allocateSize);

m_zstream.next_out = output.data();
m_zstream.avail_out = output.size();
@@ -135,6 +145,10 @@ ExceptionOr<RefPtr<JSC::ArrayBuffer>> CompressionStreamEncoder::compress(const u
storage.append(output);
}

return storage.takeAsArrayBuffer();
auto compressedData = storage.takeAsArrayBuffer();
if (!compressedData)
return Exception { OutOfMemoryError };

return compressedData;
}
} // namespace WebCore
@@ -118,7 +118,17 @@ ExceptionOr<RefPtr<JSC::ArrayBuffer>> DecompressionStreamDecoder::decompressZlib
}

while (shouldDecompress) {
auto output = Vector<uint8_t>(allocateSize);
auto output = Vector<uint8_t>();
if (!output.tryReserveInitialCapacity(allocateSize)) {
allocateSize /= 4;

if (allocateSize < startingAllocationSize)
return Exception { OutOfMemoryError };

continue;
}

output.resize(allocateSize);

m_zstream.next_out = output.data();
m_zstream.avail_out = output.size();
@@ -143,7 +153,11 @@ ExceptionOr<RefPtr<JSC::ArrayBuffer>> DecompressionStreamDecoder::decompressZlib
storage.append(output);
}

return storage.takeAsArrayBuffer();
auto decompressedData = storage.takeAsArrayBuffer();
if (!decompressedData)
return Exception { OutOfMemoryError };

return decompressedData;
}

#if PLATFORM(COCOA)
@@ -176,7 +190,17 @@ ExceptionOr<RefPtr<JSC::ArrayBuffer>> DecompressionStreamDecoder::decompressAppl
m_stream.src_size = inputLength;

while (shouldDecompress) {
auto output = Vector<uint8_t>(allocateSize);
auto output = Vector<uint8_t>();
if (!output.tryReserveInitialCapacity(allocateSize)) {
allocateSize /= 4;

if (allocateSize < startingAllocationSize)
return Exception { OutOfMemoryError };

continue;
}

output.resize(allocateSize);

m_stream.dst_ptr = output.data();
m_stream.dst_size = output.size();
@@ -201,7 +225,11 @@ ExceptionOr<RefPtr<JSC::ArrayBuffer>> DecompressionStreamDecoder::decompressAppl
storage.append(output);
}

return storage.takeAsArrayBuffer();
auto decompressedData = storage.takeAsArrayBuffer();
if (!decompressedData)
return Exception { OutOfMemoryError };

return decompressedData;
}
#endif

0 comments on commit 7a01e74

Please sign in to comment.