瀏覽代碼

Everywhere: Make ByteBuffer::{create_*,copy}() OOM-safe

Ali Mohammad Pur 3 年之前
父節點
當前提交
97e97bccab
共有 100 個文件被更改,包括 586 次插入260 次删除
  1. 2 1
      AK/Base64.cpp
  2. 20 13
      AK/ByteBuffer.h
  3. 6 2
      AK/Hex.cpp
  4. 3 2
      AK/MemoryStream.h
  5. 2 1
      AK/String.cpp
  6. 2 1
      AK/StringBuilder.cpp
  7. 26 7
      Kernel/FileSystem/Ext2FileSystem.cpp
  8. 22 9
      Kernel/Net/NE2000NetworkAdapter.cpp
  9. 6 2
      Kernel/Net/NetworkAdapter.cpp
  10. 13 3
      Kernel/Random.h
  11. 3 2
      Kernel/Storage/IDEChannel.cpp
  12. 8 2
      Kernel/Storage/Partition/GUIDPartitionTable.cpp
  13. 2 2
      Kernel/Storage/Partition/MBRPartitionTable.cpp
  14. 6 2
      Kernel/Storage/StorageDevice.cpp
  15. 1 1
      Meta/Lagom/Fuzzers/FuzzFlacLoader.cpp
  16. 2 2
      Meta/Lagom/Fuzzers/FuzzIMAPParser.cpp
  17. 1 2
      Meta/Lagom/Fuzzers/FuzzMD5.cpp
  18. 1 2
      Meta/Lagom/Fuzzers/FuzzRSAKeyParsing.cpp
  19. 1 2
      Meta/Lagom/Fuzzers/FuzzSHA1.cpp
  20. 1 2
      Meta/Lagom/Fuzzers/FuzzSHA256.cpp
  21. 1 2
      Meta/Lagom/Fuzzers/FuzzSHA384.cpp
  22. 1 2
      Meta/Lagom/Fuzzers/FuzzSHA512.cpp
  23. 1 1
      Meta/Lagom/Fuzzers/FuzzWAVLoader.cpp
  24. 1 2
      Meta/Lagom/Fuzzers/FuzzZip.cpp
  25. 3 3
      Tests/AK/TestByteBuffer.cpp
  26. 6 1
      Tests/Kernel/stress-writeread.cpp
  27. 1 1
      Tests/LibC/TestSnprintf.cpp
  28. 1 1
      Tests/LibC/TestStrlcpy.cpp
  29. 3 3
      Tests/LibCompress/TestDeflate.cpp
  30. 1 1
      Tests/LibCompress/TestGzip.cpp
  31. 18 18
      Tests/LibCrypto/TestAES.cpp
  32. 1 1
      Tests/LibCrypto/TestRSA.cpp
  33. 1 1
      Tests/LibIMAP/TestQuotedPrintable.cpp
  34. 2 2
      Tests/LibTLS/TestTLSHandshake.cpp
  35. 1 2
      Userland/Applications/FontEditor/GlyphEditorWidget.cpp
  36. 6 1
      Userland/Applications/HexEditor/HexEditorWidget.cpp
  37. 1 2
      Userland/Applications/ImageViewer/ViewWidget.cpp
  38. 1 1
      Userland/Applications/PixelPaint/Image.cpp
  39. 1 1
      Userland/Applications/PixelPaint/Image.h
  40. 1 1
      Userland/Applications/PixelPaint/ProjectLoader.cpp
  41. 1 1
      Userland/Applications/Spreadsheet/ExportDialog.cpp
  42. 1 1
      Userland/Applications/Spreadsheet/Readers/Test/TestXSV.cpp
  43. 3 3
      Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp
  44. 67 20
      Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp
  45. 6 6
      Userland/DevTools/UserspaceEmulator/SoftMMU.cpp
  46. 15 9
      Userland/Libraries/LibAudio/FlacLoader.cpp
  47. 7 4
      Userland/Libraries/LibAudio/WavLoader.cpp
  48. 19 3
      Userland/Libraries/LibCore/IODevice.cpp
  49. 2 1
      Userland/Libraries/LibCore/UDPServer.cpp
  50. 8 5
      Userland/Libraries/LibCoredump/Reader.cpp
  51. 2 2
      Userland/Libraries/LibCoredump/Reader.h
  52. 14 4
      Userland/Libraries/LibCrypto/Cipher/Mode/GCM.h
  53. 1 1
      Userland/Libraries/LibCrypto/Cipher/Mode/Mode.h
  54. 3 3
      Userland/Libraries/LibCrypto/Hash/HashManager.h
  55. 1 1
      Userland/Libraries/LibCrypto/NumberTheory/ModularFunctions.cpp
  56. 1 1
      Userland/Libraries/LibCrypto/PK/Code/EMSA_PSS.h
  57. 6 1
      Userland/Libraries/LibCrypto/PK/RSA.cpp
  58. 7 1
      Userland/Libraries/LibELF/DynamicLinker.cpp
  59. 4 1
      Userland/Libraries/LibGUI/Clipboard.cpp
  60. 6 1
      Userland/Libraries/LibGfx/BMPLoader.cpp
  61. 10 2
      Userland/Libraries/LibGfx/BMPWriter.cpp
  62. 2 1
      Userland/Libraries/LibGfx/Bitmap.cpp
  63. 2 1
      Userland/Libraries/LibGfx/PNGWriter.cpp
  64. 0 1
      Userland/Libraries/LibHTTP/HttpRequest.h
  65. 7 7
      Userland/Libraries/LibHTTP/Job.cpp
  66. 6 2
      Userland/Libraries/LibIPC/Connection.h
  67. 6 2
      Userland/Libraries/LibIPC/Decoder.cpp
  68. 1 1
      Userland/Libraries/LibImageDecoderClient/Client.cpp
  69. 1 1
      Userland/Libraries/LibImageDecoderClient/Client.h
  70. 4 2
      Userland/Libraries/LibJS/AST.cpp
  71. 1 1
      Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp
  72. 1 1
      Userland/Libraries/LibJS/Runtime/ArrayBuffer.h
  73. 1 1
      Userland/Libraries/LibLine/Editor.cpp
  74. 6 2
      Userland/Libraries/LibPDF/Filter.cpp
  75. 4 1
      Userland/Libraries/LibPDF/Parser.cpp
  76. 5 1
      Userland/Libraries/LibProtocol/RequestClient.cpp
  77. 3 1
      Userland/Libraries/LibProtocol/WebSocket.cpp
  78. 2 1
      Userland/Libraries/LibSQL/Heap.cpp
  79. 1 1
      Userland/Libraries/LibTLS/Handshake.cpp
  80. 18 3
      Userland/Libraries/LibTLS/HandshakeClient.cpp
  81. 18 3
      Userland/Libraries/LibTLS/HandshakeServer.cpp
  82. 45 9
      Userland/Libraries/LibTLS/Record.cpp
  83. 12 5
      Userland/Libraries/LibTLS/Socket.cpp
  84. 2 1
      Userland/Libraries/LibTLS/TLSPacketBuilder.h
  85. 2 2
      Userland/Libraries/LibTLS/TLSv12.cpp
  86. 12 3
      Userland/Libraries/LibVideo/MatroskaReader.cpp
  87. 6 1
      Userland/Libraries/LibWasm/Parser/Parser.cpp
  88. 1 0
      Userland/Libraries/LibWasm/Types.h
  89. 2 1
      Userland/Libraries/LibWeb/Loader/Resource.cpp
  90. 2 1
      Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp
  91. 1 1
      Userland/Libraries/LibWebSocket/Message.h
  92. 9 6
      Userland/Libraries/LibWebSocket/WebSocket.cpp
  93. 1 1
      Userland/Services/DHCPClient/DHCPv4.h
  94. 5 1
      Userland/Services/RequestServer/HttpCommon.h
  95. 2 2
      Userland/Services/SpiceAgent/ClipboardServerConnection.cpp
  96. 13 11
      Userland/Services/SpiceAgent/SpiceAgent.cpp
  97. 1 1
      Userland/Services/TelnetServer/Client.cpp
  98. 13 2
      Userland/Shell/AST.cpp
  99. 3 0
      Userland/Shell/Shell.cpp
  100. 1 0
      Userland/Shell/Shell.h

+ 2 - 1
AK/Base64.cpp

@@ -87,7 +87,8 @@ ByteBuffer decode_base64(const StringView& input)
             output.append(out2);
     }
 
-    return ByteBuffer::copy(output.data(), output.size());
+    // FIXME: Handle OOM failure.
+    return ByteBuffer::copy(output).release_value();
 }
 
 String encode_base64(ReadonlyBytes input)

+ 20 - 13
AK/ByteBuffer.h

@@ -62,31 +62,35 @@ public:
         return *this;
     }
 
-    [[nodiscard]] static ByteBuffer create_uninitialized(size_t size)
+    [[nodiscard]] static Optional<ByteBuffer> create_uninitialized(size_t size)
     {
         auto buffer = ByteBuffer();
-        auto ok = buffer.try_resize(size);
-        VERIFY(ok);
-        return buffer;
+        if (!buffer.try_resize(size))
+            return {};
+        return { move(buffer) };
     }
 
-    [[nodiscard]] static ByteBuffer create_zeroed(size_t size)
+    [[nodiscard]] static Optional<ByteBuffer> create_zeroed(size_t size)
     {
-        auto buffer = create_uninitialized(size);
+        auto buffer_result = create_uninitialized(size);
+        if (!buffer_result.has_value())
+            return {};
+
+        auto& buffer = buffer_result.value();
         buffer.zero_fill();
         VERIFY(size == 0 || (buffer[0] == 0 && buffer[size - 1] == 0));
-        return buffer;
+        return buffer_result;
     }
 
-    [[nodiscard]] static ByteBuffer copy(void const* data, size_t size)
+    [[nodiscard]] static Optional<ByteBuffer> copy(void const* data, size_t size)
     {
         auto buffer = create_uninitialized(size);
-        if (size != 0)
-            __builtin_memcpy(buffer.data(), data, size);
+        if (buffer.has_value() && size != 0)
+            __builtin_memcpy(buffer->data(), data, size);
         return buffer;
     }
 
-    [[nodiscard]] static ByteBuffer copy(ReadonlyBytes bytes)
+    [[nodiscard]] static Optional<ByteBuffer> copy(ReadonlyBytes bytes)
     {
         return copy(bytes.data(), bytes.size());
     }
@@ -133,12 +137,13 @@ public:
     [[nodiscard]] void* end_pointer() { return data() + m_size; }
     [[nodiscard]] void const* end_pointer() const { return data() + m_size; }
 
+    // FIXME: Make this function handle failures too.
     [[nodiscard]] ByteBuffer slice(size_t offset, size_t size) const
     {
         // I cannot hand you a slice I don't have
         VERIFY(offset + size <= this->size());
 
-        return copy(offset_pointer(offset), size);
+        return copy(offset_pointer(offset), size).release_value();
     }
 
     void clear()
@@ -237,8 +242,10 @@ private:
         if (!other.m_inline) {
             m_outline_buffer = other.m_outline_buffer;
             m_outline_capacity = other.m_outline_capacity;
-        } else
+        } else {
+            VERIFY(other.m_size <= inline_capacity);
             __builtin_memcpy(m_inline_buffer, other.m_inline_buffer, other.m_size);
+        }
         other.m_size = 0;
         other.m_inline = true;
     }

+ 6 - 2
AK/Hex.cpp

@@ -20,7 +20,11 @@ Optional<ByteBuffer> decode_hex(const StringView& input)
     if ((input.length() % 2) != 0)
         return {};
 
-    auto output = ByteBuffer::create_zeroed(input.length() / 2);
+    auto output_result = ByteBuffer::create_zeroed(input.length() / 2);
+    if (!output_result.has_value())
+        return {};
+
+    auto& output = output_result.value();
 
     for (size_t i = 0; i < input.length() / 2; ++i) {
         const auto c1 = decode_hex_digit(input[i * 2]);
@@ -34,7 +38,7 @@ Optional<ByteBuffer> decode_hex(const StringView& input)
         output[i] = (c1 << 4) + c2;
     }
 
-    return output;
+    return output_result;
 }
 
 String encode_hex(const ReadonlyBytes input)

+ 3 - 2
AK/MemoryStream.h

@@ -224,7 +224,7 @@ public:
         size_t nwritten = 0;
         while (bytes.size() - nwritten > 0) {
             if ((m_write_offset + nwritten) % chunk_size == 0)
-                m_chunks.append(ByteBuffer::create_uninitialized(chunk_size));
+                m_chunks.append(ByteBuffer::create_uninitialized(chunk_size).release_value()); // FIXME: Handle possible OOM situation.
 
             nwritten += bytes.slice(nwritten).copy_trimmed_to(m_chunks.last().bytes().slice((m_write_offset + nwritten) % chunk_size));
         }
@@ -241,7 +241,8 @@ public:
 
     ByteBuffer copy_into_contiguous_buffer() const
     {
-        auto buffer = ByteBuffer::create_uninitialized(size());
+        // FIXME: Handle possible OOM situation.
+        auto buffer = ByteBuffer::create_uninitialized(size()).release_value();
 
         const auto nread = read_without_consuming(buffer);
         VERIFY(nread == buffer.size());

+ 2 - 1
AK/String.cpp

@@ -176,7 +176,8 @@ ByteBuffer String::to_byte_buffer() const
 {
     if (!m_impl)
         return {};
-    return ByteBuffer::copy(reinterpret_cast<const u8*>(characters()), length());
+    // FIXME: Handle OOM failure.
+    return ByteBuffer::copy(bytes()).release_value();
 }
 
 template<typename T>

+ 2 - 1
AK/StringBuilder.cpp

@@ -69,7 +69,8 @@ void StringBuilder::appendvf(char const* fmt, va_list ap)
 
 ByteBuffer StringBuilder::to_byte_buffer() const
 {
-    return ByteBuffer::copy(data(), length());
+    // FIXME: Handle OOM failure.
+    return ByteBuffer::copy(data(), length()).release_value();
 }
 
 String StringBuilder::to_string() const

+ 26 - 7
Kernel/FileSystem/Ext2FileSystem.cpp

@@ -213,7 +213,10 @@ KResult Ext2FSInode::write_indirect_block(BlockBasedFileSystem::BlockIndex block
     const auto entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block());
     VERIFY(blocks_indices.size() <= entries_per_block);
 
-    auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
+    auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
+    if (!block_contents_result.has_value())
+        return ENOMEM;
+    auto block_contents = block_contents_result.release_value();
     OutputMemoryStream stream { block_contents };
     auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
 
@@ -235,7 +238,10 @@ KResult Ext2FSInode::grow_doubly_indirect_block(BlockBasedFileSystem::BlockIndex
     VERIFY(blocks_indices.size() > old_blocks_length);
     VERIFY(blocks_indices.size() <= entries_per_doubly_indirect_block);
 
-    auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
+    auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
+    if (!block_contents_result.has_value())
+        return ENOMEM;
+    auto block_contents = block_contents_result.release_value();
     auto* block_as_pointers = (unsigned*)block_contents.data();
     OutputMemoryStream stream { block_contents };
     auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
@@ -275,7 +281,10 @@ KResult Ext2FSInode::shrink_doubly_indirect_block(BlockBasedFileSystem::BlockInd
     VERIFY(old_blocks_length >= new_blocks_length);
     VERIFY(new_blocks_length <= entries_per_doubly_indirect_block);
 
-    auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
+    auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
+    if (!block_contents_result.has_value())
+        return ENOMEM;
+    auto block_contents = block_contents_result.release_value();
     auto* block_as_pointers = (unsigned*)block_contents.data();
     auto buffer = UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<u8*>(block_as_pointers));
     TRY(fs().read_block(block, &buffer, fs().block_size()));
@@ -308,7 +317,10 @@ KResult Ext2FSInode::grow_triply_indirect_block(BlockBasedFileSystem::BlockIndex
     VERIFY(blocks_indices.size() > old_blocks_length);
     VERIFY(blocks_indices.size() <= entries_per_triply_indirect_block);
 
-    auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
+    auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
+    if (!block_contents_result.has_value())
+        return ENOMEM;
+    auto block_contents = block_contents_result.release_value();
     auto* block_as_pointers = (unsigned*)block_contents.data();
     OutputMemoryStream stream { block_contents };
     auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
@@ -351,7 +363,10 @@ KResult Ext2FSInode::shrink_triply_indirect_block(BlockBasedFileSystem::BlockInd
     VERIFY(old_blocks_length >= new_blocks_length);
     VERIFY(new_blocks_length <= entries_per_triply_indirect_block);
 
-    auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
+    auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
+    if (!block_contents_result.has_value())
+        return ENOMEM;
+    auto block_contents = block_contents_result.release_value();
     auto* block_as_pointers = (unsigned*)block_contents.data();
     auto buffer = UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<u8*>(block_as_pointers));
     TRY(fs().read_block(block, &buffer, fs().block_size()));
@@ -583,7 +598,8 @@ Vector<Ext2FS::BlockIndex> Ext2FSInode::compute_block_list_impl_internal(const e
         if (!count)
             return;
         size_t read_size = count * sizeof(u32);
-        auto array_storage = ByteBuffer::create_uninitialized(read_size);
+        // FIXME: Handle possible OOM situation.
+        auto array_storage = ByteBuffer::create_uninitialized(read_size).release_value();
         auto* array = (u32*)array_storage.data();
         auto buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)array);
         if (auto result = fs().read_block(array_block_index, &buffer, read_size, 0); result.is_error()) {
@@ -1109,7 +1125,10 @@ KResult Ext2FSInode::write_directory(Vector<Ext2FSDirectoryEntry>& entries)
 
     dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::write_directory(): New directory contents to write (size {}):", identifier(), directory_size);
 
-    auto directory_data = ByteBuffer::create_uninitialized(directory_size);
+    auto directory_data_result = ByteBuffer::create_uninitialized(directory_size);
+    if (!directory_data_result.has_value())
+        return ENOMEM;
+    auto directory_data = directory_data_result.release_value();
     OutputMemoryStream stream { directory_data };
 
     for (auto& entry : entries) {

+ 22 - 9
Kernel/Net/NE2000NetworkAdapter.cpp

@@ -251,7 +251,7 @@ UNMAP_AFTER_INIT int NE2000NetworkAdapter::ram_test()
     out8(REG_WR_REMOTEBYTECOUNT1, 0x00);
     out8(REG_WR_RECEIVECONFIGURATION, BIT_RECEIVECONFIGURATION_MON);
     out8(REG_RW_COMMAND, BIT_COMMAND_DMA_ABORT | BIT_COMMAND_START);
-    auto buffer = ByteBuffer::create_uninitialized(NE2K_RAM_SIZE);
+    Array<u8, NE2K_RAM_SIZE> buffer;
 
     const u8 patterns[3] = { 0x5a, 0xff, 0x00 };
     for (int i = 0; i < 3; ++i) {
@@ -412,22 +412,35 @@ void NE2000NetworkAdapter::receive()
         dbgln_if(NE2000_DEBUG, "NE2000NetworkAdapter: Packet received {} length={}", (packet_ok ? "intact" : "damaged"), header.length);
 
         if (packet_ok) {
-            auto packet = NetworkByteBuffer::create_uninitialized(sizeof(received_packet_header) + header.length);
-            int bytes_left = packet.size();
+            size_t bytes_in_packet = sizeof(received_packet_header) + header.length;
+
+            auto packet_result = NetworkByteBuffer::create_uninitialized(bytes_in_packet);
+            u8 drop_buffer[NE2K_PAGE_SIZE];
+            Bytes buffer { drop_buffer, array_size(drop_buffer) };
+            bool will_drop { false };
+            if (!packet_result.has_value()) {
+                dbgln("NE2000NetworkAdapter: Not enough memory for packet with length = {}, dropping.", header.length);
+                will_drop = true;
+            } else {
+                buffer = packet_result->bytes();
+            }
+
             int current_offset = 0;
             int ring_offset = header_address;
 
-            while (bytes_left > 0) {
-                int copy_size = min(bytes_left, NE2K_PAGE_SIZE);
-                rdma_read(ring_offset, packet.span().slice(current_offset, copy_size));
-                current_offset += copy_size;
+            while (bytes_in_packet > 0) {
+                int copy_size = min(bytes_in_packet, NE2K_PAGE_SIZE);
+                rdma_read(ring_offset, buffer.slice(current_offset, copy_size));
+                if (!will_drop)
+                    current_offset += copy_size;
                 ring_offset += copy_size;
-                bytes_left -= copy_size;
+                bytes_in_packet -= copy_size;
                 if (ring_offset == NE2K_RAM_RECV_END)
                     ring_offset = NE2K_RAM_RECV_BEGIN;
             }
 
-            did_receive(packet.span().slice(sizeof(received_packet_header)));
+            if (!will_drop)
+                did_receive(buffer.slice(sizeof(received_packet_header)));
         }
 
         if (header.next_packet_page == (NE2K_RAM_RECV_BEGIN >> 8))

+ 6 - 2
Kernel/Net/NetworkAdapter.cpp

@@ -33,8 +33,12 @@ void NetworkAdapter::send_packet(ReadonlyBytes packet)
 void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet)
 {
     size_t size_in_bytes = sizeof(EthernetFrameHeader) + sizeof(ARPPacket);
-    auto buffer = NetworkByteBuffer::create_zeroed(size_in_bytes);
-    auto* eth = (EthernetFrameHeader*)buffer.data();
+    auto buffer_result = NetworkByteBuffer::create_zeroed(size_in_bytes);
+    if (!buffer_result.has_value()) {
+        dbgln("Dropping ARP packet targeted at {} as there is not enough memory to buffer it", packet.target_hardware_address().to_string());
+        return;
+    }
+    auto* eth = (EthernetFrameHeader*)buffer_result->data();
     eth->set_source(mac_address());
     eth->set_destination(destination);
     eth->set_ether_type(EtherType::ARP);

+ 13 - 3
Kernel/Random.h

@@ -30,8 +30,9 @@ public:
     using HashType = HashT;
     using DigestType = typename HashT::DigestType;
 
+    // FIXME: Do something other than VERIFY()'ing inside Optional in case of OOM.
     FortunaPRNG()
-        : m_counter(ByteBuffer::create_zeroed(BlockType::block_size()))
+        : m_counter(ByteBuffer::create_zeroed(BlockType::block_size()).release_value())
     {
     }
 
@@ -95,8 +96,17 @@ private:
             }
         }
         DigestType digest = new_key.digest();
-        m_key = ByteBuffer::copy(digest.immutable_data(),
-            digest.data_length());
+        if (m_key.size() == digest.data_length()) {
+            // Avoid reallocating, just overwrite the key.
+            m_key.overwrite(0, digest.immutable_data(), digest.data_length());
+        } else {
+            auto buffer_result = ByteBuffer::copy(digest.immutable_data(), digest.data_length());
+            // If there's no memory left to copy this into, bail out.
+            if (!buffer_result.has_value())
+                return;
+
+            m_key = buffer_result.release_value();
+        }
 
         m_reseed_number++;
         m_p0_len = 0;

+ 3 - 2
Kernel/Storage/IDEChannel.cpp

@@ -379,8 +379,9 @@ UNMAP_AFTER_INIT void IDEChannel::detect_disks()
             }
         }
 
-        ByteBuffer wbuf = ByteBuffer::create_uninitialized(512);
-        ByteBuffer bbuf = ByteBuffer::create_uninitialized(512);
+        // FIXME: Handle possible OOM situation here.
+        ByteBuffer wbuf = ByteBuffer::create_uninitialized(512).release_value();
+        ByteBuffer bbuf = ByteBuffer::create_uninitialized(512).release_value();
         u8* b = bbuf.data();
         u16* w = (u16*)wbuf.data();
 

+ 8 - 2
Kernel/Storage/Partition/GUIDPartitionTable.cpp

@@ -58,7 +58,8 @@ Result<NonnullOwnPtr<GUIDPartitionTable>, PartitionTable::Error> GUIDPartitionTa
 GUIDPartitionTable::GUIDPartitionTable(const StorageDevice& device)
     : MBRPartitionTable(device)
 {
-    m_cached_header = ByteBuffer::create_zeroed(m_device->block_size());
+    // FIXME: Handle OOM failure here.
+    m_cached_header = ByteBuffer::create_zeroed(m_device->block_size()).release_value();
     VERIFY(partitions_count() == 0);
     if (!initialize())
         m_valid = false;
@@ -87,7 +88,12 @@ bool GUIDPartitionTable::initialize()
         return false;
     }
 
-    auto entries_buffer = ByteBuffer::create_zeroed(m_device->block_size());
+    auto entries_buffer_result = ByteBuffer::create_zeroed(m_device->block_size());
+    if (!entries_buffer_result.has_value()) {
+        dbgln("GUIPartitionTable: not enough memory for entries buffer");
+        return false;
+    }
+    auto entries_buffer = entries_buffer_result.release_value();
     auto raw_entries_buffer = UserOrKernelBuffer::for_kernel_buffer(entries_buffer.data());
     size_t raw_byte_index = header().partition_array_start_lba * m_device->block_size();
     for (size_t entry_index = 0; entry_index < header().entries_count; entry_index++) {

+ 2 - 2
Kernel/Storage/Partition/MBRPartitionTable.cpp

@@ -47,7 +47,7 @@ bool MBRPartitionTable::read_boot_record()
 MBRPartitionTable::MBRPartitionTable(const StorageDevice& device, u32 start_lba)
     : PartitionTable(device)
     , m_start_lba(start_lba)
-    , m_cached_header(ByteBuffer::create_zeroed(m_device->block_size()))
+    , m_cached_header(ByteBuffer::create_zeroed(m_device->block_size()).release_value()) // FIXME: Do something sensible if this fails because of OOM.
 {
     if (!read_boot_record() || !initialize())
         return;
@@ -68,7 +68,7 @@ MBRPartitionTable::MBRPartitionTable(const StorageDevice& device, u32 start_lba)
 MBRPartitionTable::MBRPartitionTable(const StorageDevice& device)
     : PartitionTable(device)
     , m_start_lba(0)
-    , m_cached_header(ByteBuffer::create_zeroed(m_device->block_size()))
+    , m_cached_header(ByteBuffer::create_zeroed(m_device->block_size()).release_value()) // FIXME: Do something sensible if this fails because of OOM.
 {
     if (!read_boot_record() || contains_ebr() || is_protective_mbr() || !initialize())
         return;

+ 6 - 2
Kernel/Storage/StorageDevice.cpp

@@ -73,7 +73,10 @@ KResultOr<size_t> StorageDevice::read(FileDescription&, u64 offset, UserOrKernel
     off_t pos = whole_blocks * block_size();
 
     if (remaining > 0) {
-        auto data = ByteBuffer::create_uninitialized(block_size());
+        auto data_result = ByteBuffer::create_uninitialized(block_size());
+        if (!data_result.has_value())
+            return ENOMEM;
+        auto data = data_result.release_value();
         auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data.data());
         auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size());
         auto result = read_request->wait();
@@ -141,7 +144,8 @@ KResultOr<size_t> StorageDevice::write(FileDescription&, u64 offset, const UserO
     // partial write, we have to read the block's content first, modify it,
     // then write the whole block back to the disk.
     if (remaining > 0) {
-        auto data = ByteBuffer::create_zeroed(block_size());
+        // FIXME: Do something sensible with this OOM scenario.
+        auto data = ByteBuffer::create_zeroed(block_size()).release_value();
         auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data.data());
 
         {

+ 1 - 1
Meta/Lagom/Fuzzers/FuzzFlacLoader.cpp

@@ -10,7 +10,7 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    auto flac_data = ByteBuffer::copy(data, size);
+    auto flac_data = ByteBuffer::copy(data, size).release_value();
     auto flac = make<Audio::FlacLoaderPlugin>(flac_data);
 
     if (!flac->sniff())

+ 2 - 2
Meta/Lagom/Fuzzers/FuzzIMAPParser.cpp

@@ -11,7 +11,7 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
     auto parser = IMAP::Parser();
-    parser.parse(ByteBuffer::copy(data, size), true);
-    parser.parse(ByteBuffer::copy(data, size), false);
+    parser.parse(ByteBuffer::copy(data, size).release_value(), true);
+    parser.parse(ByteBuffer::copy(data, size).release_value(), false);
     return 0;
 }

+ 1 - 2
Meta/Lagom/Fuzzers/FuzzMD5.cpp

@@ -10,7 +10,6 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    auto buffer = ByteBuffer::copy(data, size);
-    Crypto::Hash::MD5::hash(buffer);
+    Crypto::Hash::MD5::hash(data, size);
     return 0;
 }

+ 1 - 2
Meta/Lagom/Fuzzers/FuzzRSAKeyParsing.cpp

@@ -10,7 +10,6 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    ByteBuffer rsa_data = ByteBuffer::copy(data, size);
-    Crypto::PK::RSA::parse_rsa_key(rsa_data);
+    Crypto::PK::RSA::parse_rsa_key({ data, size });
     return 0;
 }

+ 1 - 2
Meta/Lagom/Fuzzers/FuzzSHA1.cpp

@@ -10,7 +10,6 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    auto buffer = ByteBuffer::copy(data, size);
-    Crypto::Hash::SHA1::hash(buffer);
+    Crypto::Hash::SHA1::hash(data, size);
     return 0;
 }

+ 1 - 2
Meta/Lagom/Fuzzers/FuzzSHA256.cpp

@@ -10,7 +10,6 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    auto buffer = ByteBuffer::copy(data, size);
-    Crypto::Hash::SHA256::hash(buffer);
+    Crypto::Hash::SHA256::hash(data, size);
     return 0;
 }

+ 1 - 2
Meta/Lagom/Fuzzers/FuzzSHA384.cpp

@@ -10,7 +10,6 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    auto buffer = ByteBuffer::copy(data, size);
-    Crypto::Hash::SHA384::hash(buffer);
+    Crypto::Hash::SHA384::hash(data, size);
     return 0;
 }

+ 1 - 2
Meta/Lagom/Fuzzers/FuzzSHA512.cpp

@@ -10,7 +10,6 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    auto buffer = ByteBuffer::copy(data, size);
-    Crypto::Hash::SHA512::hash(buffer);
+    Crypto::Hash::SHA512::hash(data, size);
     return 0;
 }

+ 1 - 1
Meta/Lagom/Fuzzers/FuzzWAVLoader.cpp

@@ -10,7 +10,7 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    auto wav_data = ByteBuffer::copy(data, size);
+    auto wav_data = ByteBuffer::copy(data, size).release_value();
     auto wav = make<Audio::WavLoaderPlugin>(wav_data);
 
     if (!wav->sniff())

+ 1 - 2
Meta/Lagom/Fuzzers/FuzzZip.cpp

@@ -10,8 +10,7 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
-    ByteBuffer zip_data = ByteBuffer::copy(data, size);
-    auto zip_file = Archive::Zip::try_create(zip_data);
+    auto zip_file = Archive::Zip::try_create({ data, size });
     if (!zip_file.has_value())
         return 0;
 

+ 3 - 3
Tests/AK/TestByteBuffer.cpp

@@ -10,10 +10,10 @@
 
 TEST_CASE(equality_operator)
 {
-    ByteBuffer a = ByteBuffer::copy("Hello, world", 7);
-    ByteBuffer b = ByteBuffer::copy("Hello, friend", 7);
+    ByteBuffer a = ByteBuffer::copy("Hello, world", 7).release_value();
+    ByteBuffer b = ByteBuffer::copy("Hello, friend", 7).release_value();
     // `a` and `b` are both "Hello, ".
-    ByteBuffer c = ByteBuffer::copy("asdf", 4);
+    ByteBuffer c = ByteBuffer::copy("asdf", 4).release_value();
     ByteBuffer d;
     EXPECT_EQ(a == a, true);
     EXPECT_EQ(a == b, true);

+ 6 - 1
Tests/Kernel/stress-writeread.cpp

@@ -84,7 +84,12 @@ int main(int argc, char** argv)
     args_parser.add_positional_argument(target, "Target device/file path", "target");
     args_parser.parse(argc, argv);
 
-    auto buffer = AK::ByteBuffer::create_zeroed(block_size);
+    auto buffer_result = AK::ByteBuffer::create_zeroed(block_size);
+    if (!buffer_result.has_value()) {
+        warnln("Failed to allocate a buffer of {} bytes", block_size);
+        return EXIT_FAILURE;
+    }
+    auto buffer = buffer_result.release_value();
 
     int fd = open(target, O_CREAT | O_RDWR, 0666);
     if (fd < 0) {

+ 1 - 1
Tests/LibC/TestSnprintf.cpp

@@ -53,7 +53,7 @@ static bool test_single(const Testcase& testcase)
     }
 
     // Setup
-    ByteBuffer actual = ByteBuffer::create_uninitialized(SANDBOX_CANARY_SIZE + testcase.dest_n + SANDBOX_CANARY_SIZE);
+    ByteBuffer actual = ByteBuffer::create_uninitialized(SANDBOX_CANARY_SIZE + testcase.dest_n + SANDBOX_CANARY_SIZE).release_value();
     fill_with_random(actual.data(), actual.size());
     ByteBuffer expected = actual;
     VERIFY(actual.offset_pointer(0) != expected.offset_pointer(0));

+ 1 - 1
Tests/LibC/TestStrlcpy.cpp

@@ -55,7 +55,7 @@ static bool test_single(const Testcase& testcase)
     }
 
     // Setup
-    ByteBuffer actual = ByteBuffer::create_uninitialized(SANDBOX_CANARY_SIZE + testcase.dest_n + SANDBOX_CANARY_SIZE);
+    ByteBuffer actual = ByteBuffer::create_uninitialized(SANDBOX_CANARY_SIZE + testcase.dest_n + SANDBOX_CANARY_SIZE).release_value();
     fill_with_random(actual.data(), actual.size());
     ByteBuffer expected = actual;
     VERIFY(actual.offset_pointer(0) != expected.offset_pointer(0));

+ 3 - 3
Tests/LibCompress/TestDeflate.cpp

@@ -113,7 +113,7 @@ TEST_CASE(deflate_decompress_zeroes)
 
 TEST_CASE(deflate_round_trip_store)
 {
-    auto original = ByteBuffer::create_uninitialized(1024);
+    auto original = ByteBuffer::create_uninitialized(1024).release_value();
     fill_with_random(original.data(), 1024);
     auto compressed = Compress::DeflateCompressor::compress_all(original, Compress::DeflateCompressor::CompressionLevel::STORE);
     EXPECT(compressed.has_value());
@@ -124,7 +124,7 @@ TEST_CASE(deflate_round_trip_store)
 
 TEST_CASE(deflate_round_trip_compress)
 {
-    auto original = ByteBuffer::create_zeroed(2048);
+    auto original = ByteBuffer::create_zeroed(2048).release_value();
     fill_with_random(original.data(), 1024); // we pre-filled the second half with 0s to make sure we test back references as well
     // Since the different levels just change how much time is spent looking for better matches, just use fast here to reduce test time
     auto compressed = Compress::DeflateCompressor::compress_all(original, Compress::DeflateCompressor::CompressionLevel::FAST);
@@ -137,7 +137,7 @@ TEST_CASE(deflate_round_trip_compress)
 TEST_CASE(deflate_round_trip_compress_large)
 {
     auto size = Compress::DeflateCompressor::block_size * 2;
-    auto original = ByteBuffer::create_uninitialized(size); // Compress a buffer larger than the maximum block size to test the sliding window mechanism
+    auto original = ByteBuffer::create_uninitialized(size).release_value(); // Compress a buffer larger than the maximum block size to test the sliding window mechanism
     fill_with_random(original.data(), size);
     // Since the different levels just change how much time is spent looking for better matches, just use fast here to reduce test time
     auto compressed = Compress::DeflateCompressor::compress_all(original, Compress::DeflateCompressor::CompressionLevel::FAST);

+ 1 - 1
Tests/LibCompress/TestGzip.cpp

@@ -87,7 +87,7 @@ TEST_CASE(gzip_decompress_repeat_around_buffer)
 
 TEST_CASE(gzip_round_trip)
 {
-    auto original = ByteBuffer::create_uninitialized(1024);
+    auto original = ByteBuffer::create_uninitialized(1024).release_value();
     fill_with_random(original.data(), 1024);
     auto compressed = Compress::GzipCompressor::compress_all(original);
     EXPECT(compressed.has_value());

+ 18 - 18
Tests/LibCrypto/TestAES.cpp

@@ -12,7 +12,7 @@
 
 static ByteBuffer operator""_b(const char* string, size_t length)
 {
-    return ByteBuffer::copy(string, length);
+    return ByteBuffer::copy(string, length).release_value();
 }
 
 TEST_CASE(test_AES_CBC_name)
@@ -23,8 +23,8 @@ TEST_CASE(test_AES_CBC_name)
 
 static auto test_aes_cbc_encrypt = [](auto& cipher, auto& result) {
     auto in = "This is a test! This is another test!"_b;
-    auto out = cipher.create_aligned_buffer(in.size());
-    auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size());
+    auto out = cipher.create_aligned_buffer(in.size()).release_value();
+    auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size()).release_value();
     auto out_span = out.bytes();
     cipher.encrypt(in, out_span, iv);
     EXPECT_EQ(out.size(), sizeof(result));
@@ -84,9 +84,9 @@ TEST_CASE(test_AES_CBC_encrypt_with_unsigned_256bit_key)
 
 static auto test_aes_cbc_decrypt = [](auto& cipher, auto& result, auto result_len) {
     auto true_value = "This is a test! This is another test!";
-    auto in = ByteBuffer::copy(result, result_len);
-    auto out = cipher.create_aligned_buffer(in.size());
-    auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size());
+    auto in = ByteBuffer::copy(result, result_len).release_value();
+    auto out = cipher.create_aligned_buffer(in.size()).release_value();
+    auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size()).release_value();
     auto out_span = out.bytes();
     cipher.decrypt(in, out_span, iv);
     EXPECT_EQ(out_span.size(), strlen(true_value));
@@ -142,7 +142,7 @@ TEST_CASE(test_AES_CTR_name)
 static auto test_aes_ctr_encrypt = [](auto key, auto ivec, auto in, auto out_expected) {
     // nonce is already included in ivec.
     Crypto::Cipher::AESCipher::CTRMode cipher(key, 8 * key.size(), Crypto::Cipher::Intent::Encryption);
-    ByteBuffer out_actual = ByteBuffer::create_zeroed(in.size());
+    ByteBuffer out_actual = ByteBuffer::create_zeroed(in.size()).release_value();
     Bytes out_span = out_actual.bytes();
     cipher.encrypt(in, out_span, ivec);
     EXPECT_EQ(out_expected.size(), out_actual.size());
@@ -309,7 +309,7 @@ TEST_CASE(test_AES_CTR_256bit_encrypt_36bytes_with_high_counter)
 static auto test_aes_ctr_decrypt = [](auto key, auto ivec, auto in, auto out_expected) {
     // nonce is already included in ivec.
     Crypto::Cipher::AESCipher::CTRMode cipher(key, 8 * key.size(), Crypto::Cipher::Intent::Decryption);
-    ByteBuffer out_actual = ByteBuffer::create_zeroed(in.size());
+    ByteBuffer out_actual = ByteBuffer::create_zeroed(in.size()).release_value();
     auto out_span = out_actual.bytes();
     cipher.decrypt(in, out_span, ivec);
     EXPECT_EQ(out_expected.size(), out_span.size());
@@ -347,7 +347,7 @@ TEST_CASE(test_AES_GCM_128bit_encrypt_empty)
     Crypto::Cipher::AESCipher::GCMMode cipher("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, 128, Crypto::Cipher::Intent::Encryption);
     u8 result_tag[] { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a };
     Bytes out;
-    auto tag = ByteBuffer::create_uninitialized(16);
+    auto tag = ByteBuffer::create_uninitialized(16).release_value();
     cipher.encrypt({}, out, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b.bytes(), {}, tag);
     EXPECT(memcmp(result_tag, tag.data(), tag.size()) == 0);
 }
@@ -357,8 +357,8 @@ TEST_CASE(test_AES_GCM_128bit_encrypt_zeros)
     Crypto::Cipher::AESCipher::GCMMode cipher("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, 128, Crypto::Cipher::Intent::Encryption);
     u8 result_tag[] { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf };
     u8 result_ct[] { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 };
-    auto tag = ByteBuffer::create_uninitialized(16);
-    auto out = ByteBuffer::create_uninitialized(16);
+    auto tag = ByteBuffer::create_uninitialized(16).release_value();
+    auto out = ByteBuffer::create_uninitialized(16).release_value();
     auto out_bytes = out.bytes();
     cipher.encrypt("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b.bytes(), out_bytes, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b.bytes(), {}, tag);
     EXPECT(memcmp(result_ct, out.data(), out.size()) == 0);
@@ -370,8 +370,8 @@ TEST_CASE(test_AES_GCM_128bit_encrypt_multiple_blocks_with_iv)
     Crypto::Cipher::AESCipher::GCMMode cipher("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"_b, 128, Crypto::Cipher::Intent::Encryption);
     u8 result_tag[] { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 };
     u8 result_ct[] { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 };
-    auto tag = ByteBuffer::create_uninitialized(16);
-    auto out = ByteBuffer::create_uninitialized(64);
+    auto tag = ByteBuffer::create_uninitialized(16).release_value();
+    auto out = ByteBuffer::create_uninitialized(64).release_value();
     auto out_bytes = out.bytes();
     cipher.encrypt(
         "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55"_b.bytes(),
@@ -388,8 +388,8 @@ TEST_CASE(test_AES_GCM_128bit_encrypt_with_aad)
     Crypto::Cipher::AESCipher::GCMMode cipher("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"_b, 128, Crypto::Cipher::Intent::Encryption);
     u8 result_tag[] { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 };
     u8 result_ct[] { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 };
-    auto tag = ByteBuffer::create_uninitialized(16);
-    auto out = ByteBuffer::create_uninitialized(64);
+    auto tag = ByteBuffer::create_uninitialized(16).release_value();
+    auto out = ByteBuffer::create_uninitialized(64).release_value();
     auto out_bytes = out.bytes();
     cipher.encrypt(
         "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55"_b.bytes(),
@@ -417,7 +417,7 @@ TEST_CASE(test_AES_GCM_128bit_decrypt_zeros)
     u8 input_tag[] { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf };
     u8 input_ct[] { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 };
     u8 result_pt[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-    auto out = ByteBuffer::create_uninitialized(16);
+    auto out = ByteBuffer::create_uninitialized(16).release_value();
     auto out_bytes = out.bytes();
     auto consistency = cipher.decrypt({ input_ct, 16 }, out_bytes, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b.bytes(), {}, { input_tag, 16 });
     EXPECT_EQ(consistency, Crypto::VerificationConsistency::Consistent);
@@ -430,7 +430,7 @@ TEST_CASE(test_AES_GCM_128bit_decrypt_multiple_blocks_with_iv)
     u8 input_tag[] { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf };
     u8 input_ct[] { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 };
     u8 result_pt[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-    auto out = ByteBuffer::create_uninitialized(16);
+    auto out = ByteBuffer::create_uninitialized(16).release_value();
     auto out_bytes = out.bytes();
     auto consistency = cipher.decrypt({ input_ct, 16 }, out_bytes, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b.bytes(), {}, { input_tag, 16 });
     EXPECT_EQ(consistency, Crypto::VerificationConsistency::Consistent);
@@ -443,7 +443,7 @@ TEST_CASE(test_AES_GCM_128bit_decrypt_multiple_blocks_with_aad)
     u8 input_tag[] { 0x93, 0xae, 0x16, 0x97, 0x49, 0xa3, 0xbf, 0x39, 0x4f, 0x61, 0xb7, 0xc1, 0xb1, 0x2, 0x4f, 0x60 };
     u8 input_ct[] { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 };
     u8 result_pt[] { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 };
-    auto out = ByteBuffer::create_uninitialized(64);
+    auto out = ByteBuffer::create_uninitialized(64).release_value();
     auto out_bytes = out.bytes();
     auto consistency = cipher.decrypt(
         { input_ct, 64 },

+ 1 - 1
Tests/LibCrypto/TestRSA.cpp

@@ -12,7 +12,7 @@
 
 static ByteBuffer operator""_b(const char* string, size_t length)
 {
-    return ByteBuffer::copy(string, length);
+    return ByteBuffer::copy(string, length).release_value();
 }
 
 TEST_CASE(test_RSA_raw_encrypt)

+ 1 - 1
Tests/LibIMAP/TestQuotedPrintable.cpp

@@ -17,7 +17,7 @@ TEST_CASE(test_decode)
 
     auto decode_equal_byte_buffer = [](const char* input, const char* expected, size_t expected_length) {
         auto decoded = IMAP::decode_quoted_printable(StringView(input));
-        EXPECT(decoded == ByteBuffer::copy(expected, expected_length));
+        EXPECT(decoded == *ByteBuffer::copy(expected, expected_length));
     };
 
     decode_equal("hello world", "hello world");

+ 2 - 2
Tests/LibTLS/TestTLSHandshake.cpp

@@ -18,7 +18,7 @@ constexpr const char* DEFAULT_SERVER { "www.google.com" };
 
 static ByteBuffer operator""_b(const char* string, size_t length)
 {
-    return ByteBuffer::copy(string, length);
+    return ByteBuffer::copy(string, length).release_value();
 }
 
 Vector<Certificate> load_certificates();
@@ -69,7 +69,7 @@ TEST_CASE(test_TLS_hello_handshake)
     RefPtr<TLS::TLSv12> tls = TLS::TLSv12::construct(nullptr);
     tls->set_root_certificates(s_root_ca_certificates);
     bool sent_request = false;
-    ByteBuffer contents = ByteBuffer::create_uninitialized(0);
+    ByteBuffer contents;
     tls->on_tls_ready_to_write = [&](TLS::TLSv12& tls) {
         if (sent_request)
             return;

+ 1 - 2
Userland/Applications/FontEditor/GlyphEditorWidget.cpp

@@ -80,8 +80,7 @@ void GlyphEditorWidget::copy_glyph()
     metadata.set("width", String::number(bitmap.width()));
     metadata.set("height", String::number(bitmap.height()));
 
-    auto data = ByteBuffer::copy(&bits[0], bitmap.width() * bitmap.height());
-    GUI::Clipboard::the().set_data(data, "glyph/x-fonteditor", metadata);
+    GUI::Clipboard::the().set_data(ReadonlyBytes(&bits[0], bitmap.width() * bitmap.height()), "glyph/x-fonteditor", metadata);
 }
 
 void GlyphEditorWidget::paste_glyph()

+ 6 - 1
Userland/Applications/HexEditor/HexEditorWidget.cpp

@@ -75,7 +75,12 @@ HexEditorWidget::HexEditorWidget()
             auto file_size = value.to_int();
             if (file_size.has_value() && file_size.value() > 0) {
                 m_document_dirty = false;
-                m_editor->set_buffer(ByteBuffer::create_zeroed(file_size.value()));
+                auto buffer_result = ByteBuffer::create_zeroed(file_size.value());
+                if (!buffer_result.has_value()) {
+                    GUI::MessageBox::show(window(), "Entered file size is too large.", "Error", GUI::MessageBox::Type::Error);
+                    return;
+                }
+                m_editor->set_buffer(buffer_result.release_value());
                 set_path({});
                 update_title();
             } else {

+ 1 - 2
Userland/Applications/ImageViewer/ViewWidget.cpp

@@ -242,8 +242,7 @@ void ViewWidget::load_from_file(const String& path)
     // Spawn a new ImageDecoder service process and connect to it.
     auto client = ImageDecoderClient::Client::construct();
 
-    // FIXME: Find a way to avoid the memory copying here.
-    auto decoded_image_or_error = client->decode_image(ByteBuffer::copy(mapped_file.bytes()));
+    auto decoded_image_or_error = client->decode_image(mapped_file.bytes());
     if (!decoded_image_or_error.has_value()) {
         show_error();
         return;

+ 1 - 1
Userland/Applications/PixelPaint/Image.cpp

@@ -56,7 +56,7 @@ void Image::paint_into(GUI::Painter& painter, Gfx::IntRect const& dest_rect) con
     }
 }
 
-RefPtr<Gfx::Bitmap> Image::try_decode_bitmap(ByteBuffer const& bitmap_data)
+RefPtr<Gfx::Bitmap> Image::try_decode_bitmap(ReadonlyBytes const& bitmap_data)
 {
     // Spawn a new ImageDecoder service process and connect to it.
     auto client = ImageDecoderClient::Client::construct();

+ 1 - 1
Userland/Applications/PixelPaint/Image.h

@@ -50,7 +50,7 @@ public:
     static Result<NonnullRefPtr<Image>, String> try_create_from_pixel_paint_json(JsonObject const&);
     static RefPtr<Image> try_create_from_bitmap(NonnullRefPtr<Gfx::Bitmap>);
 
-    static RefPtr<Gfx::Bitmap> try_decode_bitmap(const ByteBuffer& bitmap_data);
+    static RefPtr<Gfx::Bitmap> try_decode_bitmap(const ReadonlyBytes& bitmap_data);
 
     // This generates a new Bitmap with the final image (all layers composed according to their attributes.)
     RefPtr<Gfx::Bitmap> try_compose_bitmap(Gfx::BitmapFormat format) const;

+ 1 - 1
Userland/Applications/PixelPaint/ProjectLoader.cpp

@@ -35,7 +35,7 @@ Result<void, String> ProjectLoader::try_load_from_fd_and_close(int fd, StringVie
 
         auto& mapped_file = *file_or_error.value();
         // FIXME: Find a way to avoid the memory copy here.
-        auto bitmap = Image::try_decode_bitmap(ByteBuffer::copy(mapped_file.bytes()));
+        auto bitmap = Image::try_decode_bitmap(mapped_file.bytes());
         if (!bitmap)
             return String { "Unable to decode image"sv };
         auto image = Image::try_create_from_bitmap(bitmap.release_nonnull());

+ 1 - 1
Userland/Applications/Spreadsheet/ExportDialog.cpp

@@ -35,7 +35,7 @@ CSVExportDialogPage::CSVExportDialogPage(const Sheet& sheet)
     m_headers.extend(m_data.take_first());
 
     auto temp_template = String::formatted("{}/spreadsheet-csv-export.{}.XXXXXX", Core::StandardPaths::tempfile_directory(), getpid());
-    auto temp_path = ByteBuffer::create_uninitialized(temp_template.length() + 1);
+    auto temp_path = ByteBuffer::create_uninitialized(temp_template.length() + 1).release_value();
     auto buf = reinterpret_cast<char*>(temp_path.data());
     auto copy_ok = temp_template.copy_characters_to_buffer(buf, temp_path.size());
     VERIFY(copy_ok);

+ 1 - 1
Userland/Applications/Spreadsheet/Readers/Test/TestXSV.cpp

@@ -85,7 +85,7 @@ BENCHMARK_CASE(fairly_big_data)
 {
     constexpr auto num_rows = 100000u;
     constexpr auto line = "well,hello,friends,1,2,3,4,5,6,7,8,pizza,guacamole\n"sv;
-    auto buf = ByteBuffer::create_uninitialized((line.length() * num_rows) + 1);
+    auto buf = ByteBuffer::create_uninitialized((line.length() * num_rows) + 1).release_value();
     buf[buf.size() - 1] = '\0';
 
     for (size_t row = 0; row <= num_rows; ++row) {

+ 3 - 3
Userland/Applications/Spreadsheet/Writers/Test/TestXSVWriter.cpp

@@ -18,7 +18,7 @@ TEST_CASE(can_write)
         { 7, 8, 9 },
     };
 
-    auto buffer = ByteBuffer::create_uninitialized(1024);
+    auto buffer = ByteBuffer::create_uninitialized(1024).release_value();
     OutputMemoryStream stream { buffer };
 
     Writer::CSV csv(stream, data);
@@ -39,7 +39,7 @@ TEST_CASE(can_write_with_header)
         { 7, 8, 9 },
     };
 
-    auto buffer = ByteBuffer::create_uninitialized(1024);
+    auto buffer = ByteBuffer::create_uninitialized(1024).release_value();
     OutputMemoryStream stream { buffer };
 
     Writer::CSV csv(stream, data, { "A", "B\"", "C" });
@@ -60,7 +60,7 @@ TEST_CASE(can_write_with_different_behaviours)
         { "We\"ll", "Hello,", "   Friends" },
     };
 
-    auto buffer = ByteBuffer::create_uninitialized(1024);
+    auto buffer = ByteBuffer::create_uninitialized(1024).release_value();
     OutputMemoryStream stream { buffer };
 
     Writer::CSV csv(stream, data, { "A", "B\"", "C" }, Writer::WriterBehaviour::QuoteOnlyInFieldStart | Writer::WriterBehaviour::WriteHeaders);

+ 67 - 20
Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp

@@ -413,7 +413,10 @@ int Emulator::virt$setsockopt(FlatPtr params_addr)
     mmu().copy_from_vm(&params, params_addr, sizeof(params));
 
     if (params.option == SO_RCVTIMEO || params.option == SO_TIMESTAMP) {
-        auto host_value_buffer = ByteBuffer::create_zeroed(params.value_size);
+        auto host_value_buffer_result = ByteBuffer::create_zeroed(params.value_size);
+        if (!host_value_buffer_result.has_value())
+            return -ENOMEM;
+        auto& host_value_buffer = host_value_buffer_result.value();
         mmu().copy_from_vm(host_value_buffer.data(), (FlatPtr)params.value, params.value_size);
         int rc = setsockopt(params.sockfd, params.level, params.option, host_value_buffer.data(), host_value_buffer.size());
         if (rc < 0)
@@ -542,7 +545,10 @@ int Emulator::virt$get_process_name(FlatPtr buffer, int size)
 {
     if (size < 0)
         return -EINVAL;
-    auto host_buffer = ByteBuffer::create_zeroed((size_t)size);
+    auto host_buffer_result = ByteBuffer::create_zeroed((size_t)size);
+    if (!host_buffer_result.has_value())
+        return -ENOMEM;
+    auto& host_buffer = host_buffer_result.value();
     int rc = syscall(SC_get_process_name, host_buffer.data(), host_buffer.size());
     mmu().copy_to_vm(buffer, host_buffer.data(), host_buffer.size());
     return rc;
@@ -582,13 +588,20 @@ int Emulator::virt$recvmsg(int sockfd, FlatPtr msg_addr, int flags)
     Vector<ByteBuffer, 1> buffers;
     Vector<iovec, 1> iovs;
     for (const auto& iov : mmu_iovs) {
-        buffers.append(ByteBuffer::create_uninitialized(iov.iov_len));
+        auto buffer_result = ByteBuffer::create_uninitialized(iov.iov_len);
+        if (!buffer_result.has_value())
+            return -ENOMEM;
+        buffers.append(buffer_result.release_value());
         iovs.append({ buffers.last().data(), buffers.last().size() });
     }
 
     ByteBuffer control_buffer;
-    if (mmu_msg.msg_control)
-        control_buffer = ByteBuffer::create_uninitialized(mmu_msg.msg_controllen);
+    if (mmu_msg.msg_control) {
+        auto buffer_result = ByteBuffer::create_uninitialized(mmu_msg.msg_controllen);
+        if (!buffer_result.has_value())
+            return -ENOMEM;
+        control_buffer = buffer_result.release_value();
+    }
 
     sockaddr_storage addr;
     msghdr msg = { &addr, sizeof(addr), iovs.data(), (int)iovs.size(), mmu_msg.msg_control ? control_buffer.data() : nullptr, mmu_msg.msg_controllen, mmu_msg.msg_flags };
@@ -625,8 +638,12 @@ int Emulator::virt$sendmsg(int sockfd, FlatPtr msg_addr, int flags)
     }
 
     ByteBuffer control_buffer;
-    if (mmu_msg.msg_control)
-        control_buffer = ByteBuffer::create_uninitialized(mmu_msg.msg_controllen);
+    if (mmu_msg.msg_control) {
+        auto buffer_result = ByteBuffer::create_uninitialized(mmu_msg.msg_controllen);
+        if (!buffer_result.has_value())
+            return -ENOMEM;
+        control_buffer = buffer_result.release_value();
+    }
 
     sockaddr_storage address;
     socklen_t address_length = 0;
@@ -733,7 +750,10 @@ int Emulator::virt$getgroups(ssize_t count, FlatPtr groups)
     if (!count)
         return syscall(SC_getgroups, 0, nullptr);
 
-    auto buffer = ByteBuffer::create_uninitialized(count * sizeof(gid_t));
+    auto buffer_result = ByteBuffer::create_uninitialized(count * sizeof(gid_t));
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& buffer = buffer_result.value();
     int rc = syscall(SC_getgroups, count, buffer.data());
     if (rc < 0)
         return rc;
@@ -858,7 +878,10 @@ u32 Emulator::virt$mmap(u32 params_addr)
 
     String name_str;
     if (params.name.characters) {
-        auto name = ByteBuffer::create_uninitialized(params.name.length);
+        auto buffer_result = ByteBuffer::create_uninitialized(params.name.length);
+        if (!buffer_result.has_value())
+            return -ENOMEM;
+        auto& name = buffer_result.value();
         mmu().copy_from_vm(name.data(), (FlatPtr)params.name.characters, params.name.length);
         name_str = { name.data(), name.size() };
     }
@@ -1002,7 +1025,10 @@ u32 Emulator::virt$read(int fd, FlatPtr buffer, ssize_t size)
 {
     if (size < 0)
         return -EINVAL;
-    auto local_buffer = ByteBuffer::create_uninitialized(size);
+    auto buffer_result = ByteBuffer::create_uninitialized(size);
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& local_buffer = buffer_result.value();
     int nread = syscall(SC_read, fd, local_buffer.data(), local_buffer.size());
     if (nread < 0) {
         if (nread == -EPERM) {
@@ -1029,7 +1055,10 @@ void Emulator::virt$exit(int status)
 
 ssize_t Emulator::virt$getrandom(FlatPtr buffer, size_t buffer_size, unsigned int flags)
 {
-    auto host_buffer = ByteBuffer::create_uninitialized(buffer_size);
+    auto buffer_result = ByteBuffer::create_uninitialized(buffer_size);
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& host_buffer = buffer_result.value();
     int rc = syscall(SC_getrandom, host_buffer.data(), host_buffer.size(), flags);
     if (rc < 0)
         return rc;
@@ -1039,7 +1068,10 @@ ssize_t Emulator::virt$getrandom(FlatPtr buffer, size_t buffer_size, unsigned in
 
 int Emulator::virt$get_dir_entries(int fd, FlatPtr buffer, ssize_t size)
 {
-    auto host_buffer = ByteBuffer::create_uninitialized(size);
+    auto buffer_result = ByteBuffer::create_uninitialized(size);
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& host_buffer = buffer_result.value();
     int rc = syscall(SC_get_dir_entries, fd, host_buffer.data(), host_buffer.size());
     if (rc < 0)
         return rc;
@@ -1215,7 +1247,10 @@ int Emulator::virt$realpath(FlatPtr params_addr)
     mmu().copy_from_vm(&params, params_addr, sizeof(params));
 
     auto path = mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length);
-    auto host_buffer = ByteBuffer::create_zeroed(params.buffer.size);
+    auto buffer_result = ByteBuffer::create_zeroed(params.buffer.size);
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& host_buffer = buffer_result.value();
 
     Syscall::SC_realpath_params host_params;
     host_params.path = { (const char*)path.data(), path.size() };
@@ -1231,7 +1266,10 @@ int Emulator::virt$gethostname(FlatPtr buffer, ssize_t buffer_size)
 {
     if (buffer_size < 0)
         return -EINVAL;
-    auto host_buffer = ByteBuffer::create_zeroed(buffer_size);
+    auto buffer_result = ByteBuffer::create_zeroed(buffer_size);
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& host_buffer = buffer_result.value();
     int rc = syscall(SC_gethostname, host_buffer.data(), host_buffer.size());
     if (rc < 0)
         return rc;
@@ -1316,7 +1354,10 @@ int Emulator::virt$setpgid(pid_t pid, pid_t pgid)
 
 int Emulator::virt$ttyname(int fd, FlatPtr buffer, size_t buffer_size)
 {
-    auto host_buffer = ByteBuffer::create_zeroed(buffer_size);
+    auto buffer_result = ByteBuffer::create_zeroed(buffer_size);
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& host_buffer = buffer_result.value();
     int rc = syscall(SC_ttyname, fd, host_buffer.data(), host_buffer.size());
     if (rc < 0)
         return rc;
@@ -1326,7 +1367,10 @@ int Emulator::virt$ttyname(int fd, FlatPtr buffer, size_t buffer_size)
 
 int Emulator::virt$getcwd(FlatPtr buffer, size_t buffer_size)
 {
-    auto host_buffer = ByteBuffer::create_zeroed(buffer_size);
+    auto buffer_result = ByteBuffer::create_zeroed(buffer_size);
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& host_buffer = buffer_result.value();
     int rc = syscall(SC_getcwd, host_buffer.data(), host_buffer.size());
     if (rc < 0)
         return rc;
@@ -1436,12 +1480,12 @@ int Emulator::virt$clock_nanosleep(FlatPtr params_addr)
     params.requested_sleep = &requested_sleep;
 
     auto remaining_vm_addr = params.remaining_sleep;
-    auto remaining = ByteBuffer::create_zeroed(sizeof(timespec));
-    params.remaining_sleep = (timespec*)remaining.data();
+    timespec remaining { 0, 0 };
+    params.remaining_sleep = &remaining;
 
     int rc = syscall(SC_clock_nanosleep, &params);
     if (remaining_vm_addr)
-        mmu().copy_to_vm((FlatPtr)remaining_vm_addr, remaining.data(), sizeof(timespec));
+        mmu().copy_to_vm((FlatPtr)remaining_vm_addr, &remaining, sizeof(timespec));
 
     return rc;
 }
@@ -1452,7 +1496,10 @@ int Emulator::virt$readlink(FlatPtr params_addr)
     mmu().copy_from_vm(&params, params_addr, sizeof(params));
 
     auto path = mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length);
-    auto host_buffer = ByteBuffer::create_zeroed(params.buffer.size);
+    auto buffer_result = ByteBuffer::create_zeroed(params.buffer.size);
+    if (!buffer_result.has_value())
+        return -ENOMEM;
+    auto& host_buffer = buffer_result.value();
 
     Syscall::SC_readlink_params host_params;
     host_params.path = { (const char*)path.data(), path.size() };

+ 6 - 6
Userland/DevTools/UserspaceEmulator/SoftMMU.cpp

@@ -63,17 +63,17 @@ void SoftMMU::ensure_split_at(X86::LogicalAddress address)
     // a previous page, and that it belongs to the same region.
     auto* old_region = verify_cast<MmapRegion>(m_page_to_region_map[page_index]);
 
-    //dbgln("splitting at {:p}", address.offset());
-    //dbgln("    old region: {:p}-{:p}", old_region->base(), old_region->end() - 1);
+    // dbgln("splitting at {:p}", address.offset());
+    // dbgln("    old region: {:p}-{:p}", old_region->base(), old_region->end() - 1);
 
     NonnullOwnPtr<MmapRegion> new_region = old_region->split_at(VirtualAddress(offset));
-    //dbgln("    new region: {:p}-{:p}", new_region->base(), new_region->end() - 1);
-    //dbgln(" up old region: {:p}-{:p}", old_region->base(), old_region->end() - 1);
+    // dbgln("    new region: {:p}-{:p}", new_region->base(), new_region->end() - 1);
+    // dbgln(" up old region: {:p}-{:p}", old_region->base(), old_region->end() - 1);
 
     size_t first_page_in_region = new_region->base() / PAGE_SIZE;
     size_t last_page_in_region = (new_region->base() + new_region->size() - 1) / PAGE_SIZE;
 
-    //dbgln("  @ remapping pages {} thru {}", first_page_in_region, last_page_in_region);
+    // dbgln("  @ remapping pages {} thru {}", first_page_in_region, last_page_in_region);
 
     for (size_t page = first_page_in_region; page <= last_page_in_region; ++page) {
         VERIFY(m_page_to_region_map[page] == old_region);
@@ -321,7 +321,7 @@ void SoftMMU::copy_from_vm(void* destination, const FlatPtr source, size_t size)
 
 ByteBuffer SoftMMU::copy_buffer_from_vm(const FlatPtr source, size_t size)
 {
-    auto buffer = ByteBuffer::create_uninitialized(size);
+    auto buffer = ByteBuffer::create_uninitialized(size).release_value(); // FIXME: Handle possible OOM situation.
     copy_from_vm(buffer.data(), source, size);
     return buffer;
 }

+ 15 - 9
Userland/Libraries/LibAudio/FlacLoader.cpp

@@ -134,11 +134,11 @@ bool FlacLoaderPlugin::parse_header()
     ok = ok && (m_total_samples > 0);
     CHECK_OK("Number of samples");
     // Parse checksum into a buffer first
-    ByteBuffer md5_checksum = ByteBuffer::create_uninitialized(128 / 8);
+    Array<u8, 128 / 8> md5_checksum;
     auto md5_bytes_read = streaminfo_data.read(md5_checksum);
     ok = ok && (md5_bytes_read == md5_checksum.size());
     CHECK_OK("MD5 Checksum");
-    md5_checksum.bytes().copy_to({ m_md5_checksum, sizeof(m_md5_checksum) });
+    md5_checksum.span().copy_to({ m_md5_checksum, sizeof(m_md5_checksum) });
 
     // Parse other blocks
     // TODO: For a simple first implementation, all other blocks are skipped as allowed by the FLAC specification.
@@ -195,7 +195,12 @@ FlacRawMetadataBlock FlacLoaderPlugin::next_meta_block(InputBitStream& bit_input
     u32 block_length = bit_input.read_bits_big_endian(24);
     m_data_start_location += 3;
     CHECK_IO_ERROR();
-    ByteBuffer block_data = ByteBuffer::create_uninitialized(block_length);
+    auto block_data_result = ByteBuffer::create_uninitialized(block_length);
+    if (!block_data_result.has_value()) {
+        m_error_string = "Out of memory";
+        return FlacRawMetadataBlock {};
+    }
+    auto block_data = block_data_result.release_value();
     // Reads exactly the bytes necessary into the Bytes container
     bit_input.read(block_data);
     m_data_start_location += block_length;
@@ -544,7 +549,7 @@ FlacSubframeHeader FlacLoaderPlugin::next_subframe_header(InputBitStream& bit_st
 
     FlacSubframeType subframe_type;
     u8 order = 0;
-    //LPC has the highest bit set
+    // LPC has the highest bit set
     if ((subframe_code & 0b100000) > 0) {
         subframe_type = FlacSubframeType::LPC;
         order = (subframe_code & 0b011111) + 1;
@@ -808,9 +813,10 @@ ALWAYS_INLINE i32 decode_unsigned_exp_golomb(u8 k, InputBitStream& bit_input)
 u64 read_utf8_char(InputStream& input)
 {
     u64 character;
-    ByteBuffer single_byte_buffer = ByteBuffer::create_uninitialized(1);
-    input.read(single_byte_buffer);
-    u8 start_byte = single_byte_buffer[0];
+    u8 buffer = 0;
+    Bytes buffer_bytes { &buffer, 1 };
+    input.read(buffer_bytes);
+    u8 start_byte = buffer_bytes[0];
     // Signal byte is zero: ASCII character
     if ((start_byte & 0b10000000) == 0) {
         return start_byte;
@@ -826,8 +832,8 @@ u64 read_utf8_char(InputStream& input)
     u8 start_byte_bitmask = AK::exp2(bits_from_start_byte) - 1;
     character = start_byte_bitmask & start_byte;
     for (u8 i = length - 1; i > 0; --i) {
-        input.read(single_byte_buffer);
-        u8 current_byte = single_byte_buffer[0];
+        input.read(buffer_bytes);
+        u8 current_byte = buffer_bytes[0];
         character = (character << 6) | (current_byte & 0b00111111);
     }
     return character;

+ 7 - 4
Userland/Libraries/LibAudio/WavLoader.cpp

@@ -69,7 +69,10 @@ RefPtr<Buffer> WavLoaderPlugin::get_more_samples(size_t max_bytes_to_read_from_i
         bytes_to_read, m_num_channels, m_sample_rate,
         pcm_bits_per_sample(m_sample_format), sample_format_name(m_sample_format));
 
-    ByteBuffer sample_data = ByteBuffer::create_zeroed(bytes_to_read);
+    auto sample_data_result = ByteBuffer::create_zeroed(bytes_to_read);
+    if (!sample_data_result.has_value())
+        return nullptr;
+    auto sample_data = sample_data_result.release_value();
     m_stream->read_or_error(sample_data.bytes());
     if (m_stream->handle_any_error()) {
         return nullptr;
@@ -244,17 +247,17 @@ bool WavLoaderPlugin::parse_header()
     while (true) {
         search_byte = read_u8();
         CHECK_OK("Reading byte searching for data");
-        if (search_byte != 0x64) //D
+        if (search_byte != 0x64) // D
             continue;
 
         search_byte = read_u8();
         CHECK_OK("Reading next byte searching for data");
-        if (search_byte != 0x61) //A
+        if (search_byte != 0x61) // A
             continue;
 
         u16 search_remaining = read_u16();
         CHECK_OK("Reading remaining bytes searching for data");
-        if (search_remaining != 0x6174) //TA
+        if (search_remaining != 0x6174) // TA
             continue;
 
         data_sz = read_u32();

+ 19 - 3
Userland/Libraries/LibCore/IODevice.cpp

@@ -43,7 +43,12 @@ ByteBuffer IODevice::read(size_t max_size)
         return {};
     if (!max_size)
         return {};
-    auto buffer = ByteBuffer::create_uninitialized(max_size);
+    auto buffer_result = ByteBuffer::create_uninitialized(max_size);
+    if (!buffer_result.has_value()) {
+        dbgln("IODevice::read: Not enough memory to allocate a buffer of {} bytes", max_size);
+        return {};
+    }
+    auto buffer = buffer_result.release_value();
     auto* buffer_ptr = (char*)buffer.data();
     size_t remaining_buffer_space = buffer.size();
     size_t taken_from_buffered = 0;
@@ -166,7 +171,13 @@ ByteBuffer IODevice::read_all()
         }
         data.append((const u8*)read_buffer, nread);
     }
-    return ByteBuffer::copy(data.data(), data.size());
+
+    auto result = ByteBuffer::copy(data);
+    if (result.has_value())
+        return result.release_value();
+
+    set_error(ENOMEM);
+    return {};
 }
 
 String IODevice::read_line(size_t max_size)
@@ -186,7 +197,12 @@ String IODevice::read_line(size_t max_size)
         m_buffered_data.clear();
         return line;
     }
-    auto line = ByteBuffer::create_uninitialized(max_size + 1);
+    auto line_result = ByteBuffer::create_uninitialized(max_size + 1);
+    if (!line_result.has_value()) {
+        dbgln("IODevice::read_line: Not enough memory to allocate a buffer of {} bytes", max_size + 1);
+        return {};
+    }
+    auto line = line_result.release_value();
     size_t line_index = 0;
     while (line_index < max_size) {
         u8 ch = m_buffered_data[line_index];

+ 2 - 1
Userland/Libraries/LibCore/UDPServer.cpp

@@ -63,7 +63,8 @@ bool UDPServer::bind(const IPv4Address& address, u16 port)
 
 ByteBuffer UDPServer::receive(size_t size, sockaddr_in& in)
 {
-    auto buf = ByteBuffer::create_uninitialized(size);
+    // FIXME: Handle possible OOM situation.
+    auto buf = ByteBuffer::create_uninitialized(size).release_value();
     socklen_t in_len = sizeof(in);
     ssize_t rlen = ::recvfrom(m_fd, buf.data(), size, 0, (sockaddr*)&in, &in_len);
     if (rlen < 0) {

+ 8 - 5
Userland/Libraries/LibCoredump/Reader.cpp

@@ -18,11 +18,14 @@ OwnPtr<Reader> Reader::create(const String& path)
     auto file_or_error = MappedFile::map(path);
     if (file_or_error.is_error())
         return {};
-    return adopt_own(*new Reader(file_or_error.value()->bytes()));
+    auto decompressed_data = decompress_coredump(file_or_error.value()->bytes());
+    if (!decompressed_data.has_value())
+        return {};
+    return adopt_own_if_nonnull(new (nothrow) Reader(decompressed_data.release_value()));
 }
 
-Reader::Reader(ReadonlyBytes coredump_bytes)
-    : m_coredump_buffer(decompress_coredump(coredump_bytes))
+Reader::Reader(ByteBuffer coredump_data)
+    : m_coredump_buffer(move(coredump_data))
     , m_coredump_image(m_coredump_buffer.bytes())
 {
     size_t index = 0;
@@ -37,14 +40,14 @@ Reader::Reader(ReadonlyBytes coredump_bytes)
     VERIFY(m_notes_segment_index != -1);
 }
 
-ByteBuffer Reader::decompress_coredump(const ReadonlyBytes& raw_coredump)
+Optional<ByteBuffer> Reader::decompress_coredump(const ReadonlyBytes& raw_coredump)
 {
     if (!Compress::GzipDecompressor::is_likely_compressed(raw_coredump))
         return ByteBuffer::copy(raw_coredump); // handle old format coredumps (uncompressed)
     auto decompressed_coredump = Compress::GzipDecompressor::decompress_all(raw_coredump);
     if (!decompressed_coredump.has_value())
         return ByteBuffer::copy(raw_coredump); // if we didn't manage to decompress it, try and parse it as decompressed coredump
-    return decompressed_coredump.value();
+    return decompressed_coredump;
 }
 
 Reader::~Reader()

+ 2 - 2
Userland/Libraries/LibCoredump/Reader.h

@@ -51,9 +51,9 @@ public:
     HashMap<String, String> metadata() const;
 
 private:
-    Reader(ReadonlyBytes);
+    Reader(ByteBuffer);
 
-    static ByteBuffer decompress_coredump(const ReadonlyBytes&);
+    static Optional<ByteBuffer> decompress_coredump(const ReadonlyBytes&);
 
     class NotesEntryIterator {
     public:

+ 14 - 4
Userland/Libraries/LibCrypto/Cipher/Mode/GCM.h

@@ -66,8 +66,14 @@ public:
 
     void encrypt(const ReadonlyBytes& in, Bytes out, const ReadonlyBytes& iv_in, const ReadonlyBytes& aad, Bytes tag)
     {
-        auto iv_buf = ByteBuffer::copy(iv_in.data(), iv_in.size());
-        auto iv = iv_buf.bytes();
+        auto iv_buf_result = ByteBuffer::copy(iv_in);
+        // Not enough memory to figure out :shrug:
+        if (!iv_buf_result.has_value()) {
+            dbgln("GCM::encrypt: Not enough memory to allocate {} bytes for IV", iv_in.size());
+            return;
+        }
+
+        auto iv = iv_buf_result->bytes();
 
         // Increment the IV for block 0
         CTR<T>::increment(iv);
@@ -90,8 +96,12 @@ public:
 
     VerificationConsistency decrypt(ReadonlyBytes in, Bytes out, ReadonlyBytes iv_in, ReadonlyBytes aad, ReadonlyBytes tag)
     {
-        auto iv_buf = ByteBuffer::copy(iv_in.data(), iv_in.size());
-        auto iv = iv_buf.bytes();
+        auto iv_buf_result = ByteBuffer::copy(iv_in);
+        // Not enough memory to figure out :shrug:
+        if (!iv_buf_result.has_value())
+            return VerificationConsistency::Inconsistent;
+
+        auto iv = iv_buf_result->bytes();
 
         // Increment the IV for block 0
         CTR<T>::increment(iv);

+ 1 - 1
Userland/Libraries/LibCrypto/Cipher/Mode/Mode.h

@@ -26,7 +26,7 @@ public:
 
     const T& cipher() const { return m_cipher; }
 
-    ByteBuffer create_aligned_buffer(size_t input_size) const
+    Optional<ByteBuffer> create_aligned_buffer(size_t input_size) const
     {
         size_t remainder = (input_size + T::block_size()) % T::block_size();
         if (remainder == 0)

+ 3 - 3
Userland/Libraries/LibCrypto/Hash/HashManager.h

@@ -83,18 +83,18 @@ public:
 
     Manager()
     {
-        m_pre_init_buffer = ByteBuffer::create_zeroed(0);
+        m_pre_init_buffer = ByteBuffer();
     }
 
     Manager(const Manager& other) // NOT a copy constructor!
     {
-        m_pre_init_buffer = ByteBuffer::create_zeroed(0); // will not be used
+        m_pre_init_buffer = ByteBuffer(); // will not be used
         initialize(other.m_kind);
     }
 
     Manager(HashKind kind)
     {
-        m_pre_init_buffer = ByteBuffer::create_zeroed(0);
+        m_pre_init_buffer = ByteBuffer();
         initialize(kind);
     }
 

+ 1 - 1
Userland/Libraries/LibCrypto/NumberTheory/ModularFunctions.cpp

@@ -165,7 +165,7 @@ UnsignedBigInteger random_number(const UnsignedBigInteger& min, const UnsignedBi
     UnsignedBigInteger base;
     auto size = range.trimmed_length() * sizeof(u32) + 2;
     // "+2" is intentional (see below).
-    auto buffer = ByteBuffer::create_uninitialized(size);
+    auto buffer = ByteBuffer::create_uninitialized(size).release_value(); // FIXME: Handle possible OOM situation.
     auto* buf = buffer.data();
 
     fill_with_random(buf, size);

+ 1 - 1
Userland/Libraries/LibCrypto/PK/Code/EMSA_PSS.h

@@ -147,7 +147,7 @@ public:
     void MGF1(ReadonlyBytes seed, size_t length, Bytes out)
     {
         auto& hash_fn = this->hasher();
-        ByteBuffer T = ByteBuffer::create_zeroed(0);
+        ByteBuffer T;
         for (size_t counter = 0; counter < length / HashFunction::DigestSize - 1; ++counter) {
             hash_fn.update(seed);
             hash_fn.update((u8*)&counter, 4);

+ 6 - 1
Userland/Libraries/LibCrypto/PK/RSA.cpp

@@ -198,7 +198,12 @@ RSA::KeyPairType RSA::parse_rsa_key(ReadonlyBytes der)
         // Now just read it as a PKCS#1 DER.
         auto data = data_result.release_value();
         // FIXME: This is pretty awkward, maybe just generate a zero'd out ByteBuffer from the parser instead?
-        auto padded_data = ByteBuffer::create_zeroed(data.size_in_bytes());
+        auto padded_data_result = ByteBuffer::create_zeroed(data.size_in_bytes());
+        if (!padded_data_result.has_value()) {
+            dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#1 key parse failed: Not enough memory");
+            return keypair;
+        }
+        auto padded_data = padded_data_result.release_value();
         padded_data.overwrite(0, data.data(), data.size_in_bytes());
 
         return parse_rsa_key(padded_data.bytes());

+ 7 - 1
Userland/Libraries/LibELF/DynamicLinker.cpp

@@ -169,7 +169,13 @@ static void allocate_tls()
         return;
 
     auto page_aligned_size = align_up_to(s_total_tls_size, PAGE_SIZE);
-    ByteBuffer initial_tls_data = ByteBuffer::create_zeroed(page_aligned_size);
+    auto initial_tls_data_result = ByteBuffer::create_zeroed(page_aligned_size);
+    if (!initial_tls_data_result.has_value()) {
+        dbgln("Failed to allocate initial TLS data");
+        VERIFY_NOT_REACHED();
+    }
+
+    auto& initial_tls_data = initial_tls_data_result.value();
 
     // Initialize TLS data
     for (const auto& entry : s_loaders) {

+ 4 - 1
Userland/Libraries/LibGUI/Clipboard.cpp

@@ -56,9 +56,12 @@ Clipboard::DataAndType Clipboard::data_and_type() const
     if (!response.data().is_valid())
         return {};
     auto data = ByteBuffer::copy(response.data().data<void>(), response.data().size());
+    if (!data.has_value())
+        return {};
+
     auto type = response.mime_type();
     auto metadata = response.metadata().entries();
-    return { data, type, metadata };
+    return { data.release_value(), type, metadata };
 }
 
 RefPtr<Gfx::Bitmap> Clipboard::bitmap() const

+ 6 - 1
Userland/Libraries/LibGfx/BMPLoader.cpp

@@ -946,7 +946,12 @@ static bool uncompress_bmp_rle_data(BMPLoadingContext& context, ByteBuffer& buff
         dbgln("Suspiciously large amount of RLE data");
         return false;
     }
-    buffer = ByteBuffer::create_zeroed(buffer_size);
+    auto buffer_result = ByteBuffer::create_zeroed(buffer_size);
+    if (!buffer_result.has_value()) {
+        dbgln("Not enough memory for buffer allocation");
+        return false;
+    }
+    buffer = buffer_result.release_value();
 
     // Avoid as many if statements as possible by pulling out
     // compression-dependent actions into separate lambdas

+ 10 - 2
Userland/Libraries/LibGfx/BMPWriter.cpp

@@ -45,7 +45,11 @@ private:
 static ByteBuffer write_pixel_data(const RefPtr<Bitmap> bitmap, int pixel_row_data_size, int bytes_per_pixel, bool include_alpha_channel)
 {
     int image_size = pixel_row_data_size * bitmap->height();
-    auto buffer = ByteBuffer::create_uninitialized(image_size);
+    auto buffer_result = ByteBuffer::create_uninitialized(image_size);
+    if (!buffer_result.has_value())
+        return {};
+
+    auto buffer = buffer_result.release_value();
 
     int current_row = 0;
     for (int y = bitmap->physical_height() - 1; y >= 0; --y) {
@@ -95,7 +99,11 @@ ByteBuffer BMPWriter::dump(const RefPtr<Bitmap> bitmap, DibHeader dib_header)
 
     int pixel_row_data_size = (m_bytes_per_pixel * 8 * bitmap->width() + 31) / 32 * 4;
     int image_size = pixel_row_data_size * bitmap->height();
-    auto buffer = ByteBuffer::create_uninitialized(pixel_data_offset);
+    auto buffer_result = ByteBuffer::create_uninitialized(pixel_data_offset);
+    if (!buffer_result.has_value())
+        return {};
+
+    auto buffer = buffer_result.release_value();
 
     auto pixel_data = write_pixel_data(bitmap, pixel_row_data_size, m_bytes_per_pixel, m_include_alpha_channel);
     pixel_data = compress_pixel_data(pixel_data, m_compression);

+ 2 - 1
Userland/Libraries/LibGfx/Bitmap.cpp

@@ -247,7 +247,8 @@ RefPtr<Bitmap> Bitmap::try_create_from_serialized_byte_buffer(ByteBuffer&& buffe
 
 ByteBuffer Bitmap::serialize_to_byte_buffer() const
 {
-    auto buffer = ByteBuffer::create_uninitialized(sizeof(size_t) + 4 * sizeof(unsigned) + sizeof(BitmapFormat) + sizeof(RGBA32) * palette_size(m_format) + size_in_bytes());
+    // FIXME: Somehow handle possible OOM situation here.
+    auto buffer = ByteBuffer::create_uninitialized(sizeof(size_t) + 4 * sizeof(unsigned) + sizeof(BitmapFormat) + sizeof(RGBA32) * palette_size(m_format) + size_in_bytes()).release_value();
     OutputMemoryStream stream { buffer };
 
     auto write = [&]<typename T>(T value) {

+ 2 - 1
Userland/Libraries/LibGfx/PNGWriter.cpp

@@ -221,7 +221,8 @@ ByteBuffer PNGWriter::encode(Gfx::Bitmap const& bitmap)
     writer.add_IHDR_chunk(bitmap.width(), bitmap.height(), 8, 6, 0, 0, 0);
     writer.add_IDAT_chunk(bitmap);
     writer.add_IEND_chunk();
-    return ByteBuffer::copy(writer.m_data);
+    // FIXME: Handle OOM failure.
+    return ByteBuffer::copy(writer.m_data).release_value();
 }
 
 }

+ 0 - 1
Userland/Libraries/LibHTTP/HttpRequest.h

@@ -47,7 +47,6 @@ public:
     void set_method(Method method) { m_method = method; }
 
     ByteBuffer const& body() const { return m_body; }
-    void set_body(ReadonlyBytes body) { m_body = ByteBuffer::copy(body); }
     void set_body(ByteBuffer&& body) { m_body = move(body); }
 
     String method_name() const;

+ 7 - 7
Userland/Libraries/LibHTTP/Job.cpp

@@ -136,17 +136,17 @@ void Job::on_socket_connected()
                 return;
             auto line = read_line(PAGE_SIZE);
             if (line.is_null()) {
-                warnln("Job: Expected HTTP status");
+                dbgln("Job: Expected HTTP status");
                 return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::TransmissionFailed); });
             }
             auto parts = line.split_view(' ');
             if (parts.size() < 3) {
-                warnln("Job: Expected 3-part HTTP status, got '{}'", line);
+                dbgln("Job: Expected 3-part HTTP status, got '{}'", line);
                 return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
             }
             auto code = parts[1].to_uint();
             if (!code.has_value()) {
-                warnln("Job: Expected numeric HTTP status");
+                dbgln("Job: Expected numeric HTTP status");
                 return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
             }
             m_code = code.value();
@@ -164,7 +164,7 @@ void Job::on_socket_connected()
                     // that is not a valid trailing header.
                     return finish_up();
                 }
-                warnln("Job: Expected HTTP header");
+                dbgln("Job: Expected HTTP header");
                 return did_fail(Core::NetworkJob::Error::ProtocolFailed);
             }
             if (line.is_empty()) {
@@ -185,7 +185,7 @@ void Job::on_socket_connected()
                     // that is not a valid trailing header.
                     return finish_up();
                 }
-                warnln("Job: Expected HTTP header with key/value");
+                dbgln("Job: Expected HTTP header with key/value");
                 return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
             }
             auto name = parts[0];
@@ -196,7 +196,7 @@ void Job::on_socket_connected()
                     // that is not a valid trailing header.
                     return finish_up();
                 }
-                warnln("Job: Malformed HTTP header: '{}' ({})", line, line.length());
+                dbgln("Job: Malformed HTTP header: '{}' ({})", line, line.length());
                 return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
             }
             auto value = line.substring(name.length() + 2, line.length() - name.length() - 2);
@@ -363,7 +363,7 @@ void Job::finish_up()
     VERIFY(!m_has_scheduled_finish);
     m_state = State::Finished;
     if (!m_can_stream_response) {
-        auto flattened_buffer = ByteBuffer::create_uninitialized(m_received_size);
+        auto flattened_buffer = ByteBuffer::create_uninitialized(m_received_size).release_value(); // FIXME: Handle possible OOM situation.
         u8* flat_ptr = flattened_buffer.data();
         for (auto& received_buffer : m_received_buffers) {
             memcpy(flat_ptr, received_buffer.data(), received_buffer.size());

+ 6 - 2
Userland/Libraries/LibIPC/Connection.h

@@ -231,13 +231,17 @@ protected:
             // Sometimes we might receive a partial message. That's okay, just stash away
             // the unprocessed bytes and we'll prepend them to the next incoming message
             // in the next run of this function.
-            auto remaining_bytes = ByteBuffer::copy(bytes.data() + index, bytes.size() - index);
+            auto remaining_bytes_result = ByteBuffer::copy(bytes.span().slice(index));
+            if (!remaining_bytes_result.has_value()) {
+                dbgln("{}::drain_messages_from_peer: Failed to allocate buffer", *this);
+                return false;
+            }
             if (!m_unprocessed_bytes.is_empty()) {
                 dbgln("{}::drain_messages_from_peer: Already have unprocessed bytes", *this);
                 shutdown();
                 return false;
             }
-            m_unprocessed_bytes = remaining_bytes;
+            m_unprocessed_bytes = remaining_bytes_result.release_value();
         }
 
         if (!m_unprocessed_messages.is_empty()) {

+ 6 - 2
Userland/Libraries/LibIPC/Decoder.cpp

@@ -110,10 +110,14 @@ bool Decoder::decode(ByteBuffer& value)
         return true;
     }
     if (length == 0) {
-        value = ByteBuffer::create_uninitialized(0);
+        value = {};
         return true;
     }
-    value = ByteBuffer::create_uninitialized(length);
+    if (auto buffer_result = ByteBuffer::create_uninitialized(length); buffer_result.has_value())
+        value = buffer_result.release_value();
+    else
+        return false;
+
     m_stream >> value.bytes();
     return !m_stream.handle_any_error();
 }

+ 1 - 1
Userland/Libraries/LibImageDecoderClient/Client.cpp

@@ -20,7 +20,7 @@ void Client::die()
         on_death();
 }
 
-Optional<DecodedImage> Client::decode_image(const ByteBuffer& encoded_data)
+Optional<DecodedImage> Client::decode_image(const ReadonlyBytes& encoded_data)
 {
     if (encoded_data.is_empty())
         return {};

+ 1 - 1
Userland/Libraries/LibImageDecoderClient/Client.h

@@ -30,7 +30,7 @@ class Client final
     C_OBJECT(Client);
 
 public:
-    Optional<DecodedImage> decode_image(const ByteBuffer&);
+    Optional<DecodedImage> decode_image(const ReadonlyBytes&);
 
     Function<void()> on_death;
 

+ 4 - 2
Userland/Libraries/LibJS/AST.cpp

@@ -2106,6 +2106,8 @@ Value ArrayExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
     InterpreterNodeScope node_scope { interpreter, *this };
 
     auto* array = Array::create(global_object, 0);
+    array->indexed_properties();
+    size_t index = 0;
     for (auto& element : m_elements) {
         auto value = Value();
         if (element) {
@@ -2115,7 +2117,7 @@ Value ArrayExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
 
             if (is<SpreadExpression>(*element)) {
                 get_iterator_values(global_object, value, [&](Value iterator_value) {
-                    array->indexed_properties().append(iterator_value);
+                    array->indexed_properties().put(index++, iterator_value, default_attributes);
                     return IterationDecision::Continue;
                 });
                 if (interpreter.exception())
@@ -2123,7 +2125,7 @@ Value ArrayExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
                 continue;
             }
         }
-        array->indexed_properties().append(value);
+        array->indexed_properties().put(index++, value, default_attributes);
     }
     return array;
 }

+ 1 - 1
Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp

@@ -21,7 +21,7 @@ ArrayBuffer* ArrayBuffer::create(GlobalObject& global_object, ByteBuffer* buffer
 
 ArrayBuffer::ArrayBuffer(size_t byte_size, Object& prototype)
     : Object(prototype)
-    , m_buffer(ByteBuffer::create_zeroed(byte_size))
+    , m_buffer(ByteBuffer::create_zeroed(byte_size).release_value()) // FIXME: Handle this possible OOM failure.
     , m_detach_key(js_undefined())
 {
 }

+ 1 - 1
Userland/Libraries/LibJS/Runtime/ArrayBuffer.h

@@ -125,7 +125,7 @@ template<typename T>
 static ByteBuffer numeric_to_raw_bytes(GlobalObject& global_object, Value value, bool is_little_endian)
 {
     using UnderlyingBufferDataType = Conditional<IsSame<ClampedU8, T>, u8, T>;
-    ByteBuffer raw_bytes = ByteBuffer::create_uninitialized(sizeof(UnderlyingBufferDataType));
+    ByteBuffer raw_bytes = ByteBuffer::create_uninitialized(sizeof(UnderlyingBufferDataType)).release_value(); // FIXME: Handle possible OOM situation.
     auto flip_if_needed = [&]() {
         if (is_little_endian)
             return;

+ 1 - 1
Userland/Libraries/LibLine/Editor.cpp

@@ -185,7 +185,7 @@ Editor::Editor(Configuration configuration)
     : m_configuration(move(configuration))
 {
     m_always_refresh = m_configuration.refresh_behaviour == Configuration::RefreshBehaviour::Eager;
-    m_pending_chars = ByteBuffer::create_uninitialized(0);
+    m_pending_chars = {};
     get_terminal_size();
     m_suggestion_display = make<XtermSuggestionDisplay>(m_num_lines, m_num_columns);
 }

+ 6 - 2
Userland/Libraries/LibPDF/Filter.cpp

@@ -44,7 +44,11 @@ Optional<ByteBuffer> Filter::decode_ascii_hex(ReadonlyBytes const& bytes)
 
     // FIXME: Integrate this padding into AK/Hex?
 
-    auto output = ByteBuffer::create_zeroed(bytes.size() / 2 + 1);
+    auto output_result = ByteBuffer::create_zeroed(bytes.size() / 2 + 1);
+    if (!output_result.has_value())
+        return output_result;
+
+    auto output = output_result.release_value();
 
     for (size_t i = 0; i < bytes.size() / 2; ++i) {
         const auto c1 = decode_hex_digit(static_cast<char>(bytes[i * 2]));
@@ -61,7 +65,7 @@ Optional<ByteBuffer> Filter::decode_ascii_hex(ReadonlyBytes const& bytes)
     // Process last byte with a padded zero
     output[output.size() - 1] = decode_hex_digit(static_cast<char>(bytes[bytes.size() - 1])) * 16;
 
-    return output;
+    return { move(output) };
 };
 
 Optional<ByteBuffer> Filter::decode_ascii85(ReadonlyBytes const& bytes)

+ 4 - 1
Userland/Libraries/LibPDF/Parser.cpp

@@ -262,7 +262,10 @@ bool Parser::initialize_hint_tables()
         auto overflow_size = overflow_hint_stream->bytes().size();
         auto total_size = primary_size + overflow_size;
 
-        possible_merged_stream_buffer = ByteBuffer::create_uninitialized(total_size);
+        auto buffer_result = ByteBuffer::create_uninitialized(total_size);
+        if (!buffer_result.has_value())
+            return false;
+        possible_merged_stream_buffer = buffer_result.release_value();
         auto ok = possible_merged_stream_buffer.try_append(primary_hint_stream->bytes());
         ok = ok && possible_merged_stream_buffer.try_append(overflow_hint_stream->bytes());
         if (!ok)

+ 5 - 1
Userland/Libraries/LibProtocol/RequestClient.cpp

@@ -22,7 +22,11 @@ RefPtr<Request> RequestClient::start_request(String const& method, URL const& ur
     for (auto& it : request_headers)
         header_dictionary.add(it.key, it.value);
 
-    auto response = IPCProxy::start_request(method, url, header_dictionary, ByteBuffer::copy(request_body));
+    auto body_result = ByteBuffer::copy(request_body);
+    if (!body_result.has_value())
+        return nullptr;
+
+    auto response = IPCProxy::start_request(method, url, header_dictionary, body_result.release_value());
     auto request_id = response.request_id();
     if (request_id < 0 || !response.response_fd().has_value())
         return nullptr;

+ 3 - 1
Userland/Libraries/LibProtocol/WebSocket.cpp

@@ -27,7 +27,9 @@ void WebSocket::send(ByteBuffer binary_or_text_message, bool is_text)
 
 void WebSocket::send(StringView text_message)
 {
-    send(ByteBuffer::copy(text_message.bytes()), true);
+    auto data_result = ByteBuffer::copy(text_message.bytes());
+    VERIFY(data_result.has_value());
+    send(data_result.release_value(), true);
 }
 
 void WebSocket::close(u16 code, String reason)

+ 2 - 1
Userland/Libraries/LibSQL/Heap.cpp

@@ -203,7 +203,8 @@ void Heap::update_zero_block()
         }
     }
 
-    auto buffer = ByteBuffer::create_zeroed(BLOCKSIZE);
+    // FIXME: Handle an OOM failure here.
+    auto buffer = ByteBuffer::create_zeroed(BLOCKSIZE).release_value();
     buffer.overwrite(0, FILE_ID, strlen(FILE_ID));
     buffer.overwrite(VERSION_OFFSET, &m_version, sizeof(u32));
     buffer.overwrite(SCHEMAS_ROOT_OFFSET, &m_schemas_root, sizeof(u32));

+ 1 - 1
Userland/Libraries/LibTLS/Handshake.cpp

@@ -151,7 +151,7 @@ ByteBuffer TLSv12::build_handshake_finished()
 
     u8 out[verify_data_length];
     auto outbuffer = Bytes { out, verify_data_length };
-    auto dummy = ByteBuffer::create_zeroed(0);
+    ByteBuffer dummy;
 
     auto digest = m_context.handshake_hash.digest();
     auto hashbuf = ReadonlyBytes { digest.immutable_data(), m_context.handshake_hash.digest_size() };

+ 18 - 3
Userland/Libraries/LibTLS/HandshakeClient.cpp

@@ -192,7 +192,12 @@ void TLSv12::build_rsa_pre_master_secret(PacketBuilder& builder)
         *(u16*)random_bytes = AK::convert_between_host_and_network_endian((u16)Version::V12);
     }
 
-    m_context.premaster_key = ByteBuffer::copy(random_bytes, bytes);
+    auto premaster_key_result = ByteBuffer::copy(random_bytes, bytes);
+    if (!premaster_key_result.has_value()) {
+        dbgln("RSA premaster key generation failed, not enough memory");
+        return;
+    }
+    m_context.premaster_key = premaster_key_result.release_value();
 
     const auto& certificate_option = verify_chain_and_get_matching_certificate(m_context.extensions.SNI); // if the SNI is empty, we'll make a special case and match *a* leaf certificate.
     if (!certificate_option.has_value()) {
@@ -239,11 +244,21 @@ void TLSv12::build_dhe_rsa_pre_master_secret(PacketBuilder& builder)
 
     auto dh_random = Crypto::NumberTheory::random_number(0, dh_p);
     auto dh_Yc = Crypto::NumberTheory::ModularPower(dh_g, dh_random, dh_p);
-    auto dh_Yc_bytes = ByteBuffer::create_uninitialized(dh_key_size);
+    auto dh_Yc_bytes_result = ByteBuffer::create_uninitialized(dh_key_size);
+    if (!dh_Yc_bytes_result.has_value()) {
+        dbgln("Failed to build DHE_RSA premaster secret: not enough memory");
+        return;
+    }
+    auto dh_Yc_bytes = dh_Yc_bytes_result.release_value();
     dh_Yc.export_data(dh_Yc_bytes);
 
     auto premaster_key = Crypto::NumberTheory::ModularPower(dh_Ys, dh_random, dh_p);
-    m_context.premaster_key = ByteBuffer::create_uninitialized(dh_key_size);
+    auto premaster_key_result = ByteBuffer::create_uninitialized(dh_key_size);
+    if (!premaster_key_result.has_value()) {
+        dbgln("Failed to build DHE_RSA premaster secret: not enough memory");
+        return;
+    }
+    m_context.premaster_key = premaster_key_result.release_value();
     premaster_key.export_data(m_context.premaster_key, true);
 
     dh.p.clear();

+ 18 - 3
Userland/Libraries/LibTLS/HandshakeServer.cpp

@@ -240,15 +240,30 @@ ssize_t TLSv12::handle_dhe_rsa_server_key_exchange(ReadonlyBytes buffer)
 {
     auto dh_p_length = AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(3)));
     auto dh_p = buffer.slice(5, dh_p_length);
-    m_context.server_diffie_hellman_params.p = ByteBuffer::copy(dh_p.data(), dh_p.size());
+    auto p_result = ByteBuffer::copy(dh_p);
+    if (!p_result.has_value()) {
+        dbgln("dhe_rsa_server_key_exchange failed: Not enough memory");
+        return 0;
+    }
+    m_context.server_diffie_hellman_params.p = p_result.release_value();
 
     auto dh_g_length = AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(5 + dh_p_length)));
     auto dh_g = buffer.slice(7 + dh_p_length, dh_g_length);
-    m_context.server_diffie_hellman_params.g = ByteBuffer::copy(dh_g.data(), dh_g.size());
+    auto g_result = ByteBuffer::copy(dh_g);
+    if (!g_result.has_value()) {
+        dbgln("dhe_rsa_server_key_exchange failed: Not enough memory");
+        return 0;
+    }
+    m_context.server_diffie_hellman_params.g = g_result.release_value();
 
     auto dh_Ys_length = AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(7 + dh_p_length + dh_g_length)));
     auto dh_Ys = buffer.slice(9 + dh_p_length + dh_g_length, dh_Ys_length);
-    m_context.server_diffie_hellman_params.Ys = ByteBuffer::copy(dh_Ys.data(), dh_Ys.size());
+    auto Ys_result = ByteBuffer::copy(dh_Ys);
+    if (!Ys_result.has_value()) {
+        dbgln("dhe_rsa_server_key_exchange failed: Not enough memory");
+        return 0;
+    }
+    m_context.server_diffie_hellman_params.Ys = Ys_result.release_value();
 
     if constexpr (TLS_DEBUG) {
         dbgln("dh_p: {:hex-dump}", dh_p);

+ 45 - 9
Userland/Libraries/LibTLS/Record.cpp

@@ -97,7 +97,12 @@ void TLSv12::update_packet(ByteBuffer& packet)
 
             if (m_context.crypto.created == 1) {
                 // `buffer' will continue to be encrypted
-                auto buffer = ByteBuffer::create_uninitialized(length);
+                auto buffer_result = ByteBuffer::create_uninitialized(length);
+                if (!buffer_result.has_value()) {
+                    dbgln("LibTLS: Failed to allocate enough memory");
+                    VERIFY_NOT_REACHED();
+                }
+                auto buffer = buffer_result.release_value();
                 size_t buffer_position = 0;
                 auto iv_size = iv_length();
 
@@ -112,7 +117,12 @@ void TLSv12::update_packet(ByteBuffer& packet)
                     [&](Crypto::Cipher::AESCipher::GCMMode& gcm) {
                         VERIFY(is_aead());
                         // We need enough space for a header, the data, a tag, and the IV
-                        ct = ByteBuffer::create_uninitialized(length + header_size + iv_size + 16);
+                        auto ct_buffer_result = ByteBuffer::create_uninitialized(length + header_size + iv_size + 16);
+                        if (!ct_buffer_result.has_value()) {
+                            dbgln("LibTLS: Failed to allocate enough memory for the ciphertext");
+                            VERIFY_NOT_REACHED();
+                        }
+                        ct = ct_buffer_result.release_value();
 
                         // copy the header over
                         ct.overwrite(0, packet.data(), header_size - 2);
@@ -161,7 +171,12 @@ void TLSv12::update_packet(ByteBuffer& packet)
                     [&](Crypto::Cipher::AESCipher::CBCMode& cbc) {
                         VERIFY(!is_aead());
                         // We need enough space for a header, iv_length bytes of IV and whatever the packet contains
-                        ct = ByteBuffer::create_uninitialized(length + header_size + iv_size);
+                        auto ct_buffer_result = ByteBuffer::create_uninitialized(length + header_size + iv_size);
+                        if (!ct_buffer_result.has_value()) {
+                            dbgln("LibTLS: Failed to allocate enough memory for the ciphertext");
+                            VERIFY_NOT_REACHED();
+                        }
+                        ct = ct_buffer_result.release_value();
 
                         // copy the header over
                         ct.overwrite(0, packet.data(), header_size - 2);
@@ -179,7 +194,12 @@ void TLSv12::update_packet(ByteBuffer& packet)
 
                         VERIFY(buffer_position == buffer.size());
 
-                        auto iv = ByteBuffer::create_uninitialized(iv_size);
+                        auto iv_buffer_result = ByteBuffer::create_uninitialized(iv_size);
+                        if (!iv_buffer_result.has_value()) {
+                            dbgln("LibTLS: Failed to allocate memory for IV");
+                            VERIFY_NOT_REACHED();
+                        }
+                        auto iv = iv_buffer_result.release_value();
                         fill_with_random(iv.data(), iv.size());
 
                         // write it into the ciphertext portion of the message
@@ -266,14 +286,18 @@ ByteBuffer TLSv12::hmac_message(const ReadonlyBytes& buf, const Optional<Readonl
         hmac.update(buf2.value());
     }
     auto digest = hmac.digest();
-    auto mac = ByteBuffer::copy(digest.immutable_data(), digest.data_length());
+    auto mac_result = ByteBuffer::copy(digest.immutable_data(), digest.data_length());
+    if (!mac_result.has_value()) {
+        dbgln("Failed to calculate message HMAC: Not enough memory");
+        return {};
+    }
 
     if constexpr (TLS_DEBUG) {
         dbgln("HMAC of the block for sequence number {}", sequence_number);
-        print_buffer(mac);
+        print_buffer(*mac_result);
     }
 
-    return mac;
+    return mac_result.release_value();
 }
 
 ssize_t TLSv12::handle_message(ReadonlyBytes buffer)
@@ -336,7 +360,13 @@ ssize_t TLSv12::handle_message(ReadonlyBytes buffer)
 
                 auto packet_length = length - iv_length() - 16;
                 auto payload = plain;
-                decrypted = ByteBuffer::create_uninitialized(packet_length);
+                auto decrypted_result = ByteBuffer::create_uninitialized(packet_length);
+                if (!decrypted_result.has_value()) {
+                    dbgln("Failed to allocate memory for the packet");
+                    return_value = Error::DecryptionFailed;
+                    return;
+                }
+                decrypted = decrypted_result.release_value();
 
                 // AEAD AAD (13)
                 // Seq. no (8)
@@ -394,7 +424,13 @@ ssize_t TLSv12::handle_message(ReadonlyBytes buffer)
                 VERIFY(!is_aead());
                 auto iv_size = iv_length();
 
-                decrypted = cbc.create_aligned_buffer(length - iv_size);
+                auto decrypted_result = cbc.create_aligned_buffer(length - iv_size);
+                if (!decrypted_result.has_value()) {
+                    dbgln("Failed to allocate memory for the packet");
+                    return_value = Error::DecryptionFailed;
+                    return;
+                }
+                decrypted = decrypted_result.release_value();
                 auto iv = buffer.slice(header_size, iv_size);
 
                 Bytes decrypted_span = decrypted;

+ 12 - 5
Userland/Libraries/LibTLS/Socket.cpp

@@ -15,9 +15,8 @@ namespace TLS {
 Optional<ByteBuffer> TLSv12::read()
 {
     if (m_context.application_buffer.size()) {
-        auto buf = m_context.application_buffer.slice(0, m_context.application_buffer.size());
-        m_context.application_buffer.clear();
-        return buf;
+        auto buf = move(m_context.application_buffer);
+        return { move(buf) };
     }
     return {};
 }
@@ -47,10 +46,18 @@ String TLSv12::read_line(size_t max_size)
     if (offset > max_size)
         return {};
 
-    auto buffer = ByteBuffer::copy(start, offset);
+    auto buffer_result = ByteBuffer::copy(start, offset);
+    if (!buffer_result.has_value()) {
+        dbgln("TLS: Failed to read line, not enough memory");
+        dbgln("max_size < offset: {} < {} (size = {})", max_size, offset, m_context.application_buffer.size());
+        dbgln("-> {:32hex-dump}", ReadonlyBytes { start, offset });
+        return {};
+    }
+
+    String line { bit_cast<char const*>(start), offset, Chomp };
     m_context.application_buffer = m_context.application_buffer.slice(offset + 1, m_context.application_buffer.size() - offset - 1);
 
-    return String::copy(buffer, Chomp);
+    return line;
 }
 
 bool TLSv12::write(ReadonlyBytes buffer)

+ 2 - 1
Userland/Libraries/LibTLS/TLSPacketBuilder.h

@@ -36,7 +36,8 @@ public:
 
     PacketBuilder(MessageType type, Version version, size_t size_hint = 0xfdf)
     {
-        m_packet_data = ByteBuffer::create_uninitialized(size_hint + 16);
+        // FIXME: Handle possible OOM situation.
+        m_packet_data = ByteBuffer::create_uninitialized(size_hint + 16).release_value();
         m_current_length = 5;
         m_packet_data[0] = (u8)type;
         ByteReader::store(m_packet_data.offset_pointer(1), AK::convert_between_host_and_network_endian((u16)version));

+ 2 - 2
Userland/Libraries/LibTLS/TLSv12.cpp

@@ -35,7 +35,7 @@ void TLSv12::consume(ReadonlyBytes record)
 
     dbgln_if(TLS_DEBUG, "Consuming {} bytes", record.size());
 
-    if (!m_context.message_buffer.try_append(record.data(), record.size())) {
+    if (!m_context.message_buffer.try_append(record)) {
         dbgln("Not enough space in message buffer, dropping the record");
         return;
     }
@@ -306,7 +306,7 @@ TLSv12::TLSv12(Core::Object* parent, Options options)
 {
     m_context.options = move(options);
     m_context.is_server = false;
-    m_context.tls_buffer = ByteBuffer::create_uninitialized(0);
+    m_context.tls_buffer = {};
 #ifdef SOCK_NONBLOCK
     int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
 #else

+ 12 - 3
Userland/Libraries/LibVideo/MatroskaReader.cpp

@@ -404,18 +404,27 @@ OwnPtr<Block> MatroskaReader::parse_simple_block()
 
         for (int i = 0; i < frame_count; i++) {
             auto current_frame_size = frame_sizes.at(i);
-            block->add_frame(ByteBuffer::copy(m_streamer.data(), current_frame_size));
+            auto frame_result = ByteBuffer::copy(m_streamer.data(), current_frame_size);
+            if (!frame_result.has_value())
+                return {};
+            block->add_frame(frame_result.release_value());
             m_streamer.drop_octets(current_frame_size);
         }
     } else if (block->lacing() == Block::Lacing::FixedSize) {
         auto frame_count = m_streamer.read_octet() + 1;
         auto individual_frame_size = total_frame_content_size / frame_count;
         for (int i = 0; i < frame_count; i++) {
-            block->add_frame(ByteBuffer::copy(m_streamer.data(), individual_frame_size));
+            auto frame_result = ByteBuffer::copy(m_streamer.data(), individual_frame_size);
+            if (!frame_result.has_value())
+                return {};
+            block->add_frame(frame_result.release_value());
             m_streamer.drop_octets(individual_frame_size);
         }
     } else {
-        block->add_frame(ByteBuffer::copy(m_streamer.data(), total_frame_content_size));
+        auto frame_result = ByteBuffer::copy(m_streamer.data(), total_frame_content_size);
+        if (!frame_result.has_value())
+            return {};
+        block->add_frame(frame_result.release_value());
         m_streamer.drop_octets(total_frame_content_size);
     }
     return block;

+ 6 - 1
Userland/Libraries/LibWasm/Parser/Parser.cpp

@@ -738,7 +738,10 @@ ParseResult<CustomSection> CustomSection::parse(InputStream& stream)
     if (name.is_error())
         return name.error();
 
-    auto data_buffer = ByteBuffer::create_uninitialized(64);
+    ByteBuffer data_buffer;
+    if (!data_buffer.try_resize(64))
+        return ParseError::OutOfMemory;
+
     while (!stream.has_any_error() && !stream.unreliable_eof()) {
         char buf[16];
         auto size = stream.read({ buf, 16 });
@@ -1413,6 +1416,8 @@ String parse_error_to_string(ParseError error)
         return "The parser encountered an unimplemented feature";
     case ParseError::HugeAllocationRequested:
         return "Parsing caused an attempt to allocate a very big chunk of memory, likely malformed data";
+    case ParseError::OutOfMemory:
+        return "The parser hit an OOM condition";
     case ParseError::ExpectedFloatingImmediate:
         return "Expected a floating point immediate";
     case ParseError::ExpectedSignedImmediate:

+ 1 - 0
Userland/Libraries/LibWasm/Types.h

@@ -36,6 +36,7 @@ enum class ParseError {
     InvalidTag,
     InvalidType,
     HugeAllocationRequested,
+    OutOfMemory,
     // FIXME: This should not exist!
     NotImplemented,
 };

+ 2 - 1
Userland/Libraries/LibWeb/Loader/Resource.cpp

@@ -68,7 +68,8 @@ static String mime_type_from_content_type(const String& content_type)
 void Resource::did_load(Badge<ResourceLoader>, ReadonlyBytes data, const HashMap<String, String, CaseInsensitiveStringTraits>& headers, Optional<u32> status_code)
 {
     VERIFY(!m_loaded);
-    m_encoded_data = ByteBuffer::copy(data);
+    // FIXME: Handle OOM failure.
+    m_encoded_data = ByteBuffer::copy(data).release_value();
     m_response_headers = headers;
     m_status_code = move(status_code);
     m_loaded = true;

+ 2 - 1
Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp

@@ -212,7 +212,8 @@ DOM::ExceptionOr<void> XMLHttpRequest::send()
                 if (!weak_this)
                     return;
                 auto& xhr = const_cast<XMLHttpRequest&>(*weak_this);
-                auto response_data = ByteBuffer::copy(data);
+                // FIXME: Handle OOM failure.
+                auto response_data = ByteBuffer::copy(data).release_value();
                 // FIXME: There's currently no difference between transmitted and length.
                 u64 transmitted = response_data.size();
                 u64 length = response_data.size();

+ 1 - 1
Userland/Libraries/LibWebSocket/Message.h

@@ -15,7 +15,7 @@ class Message {
 public:
     explicit Message(String const& data)
         : m_is_text(true)
-        , m_data(ByteBuffer::copy(data.bytes()))
+        , m_data(ByteBuffer::copy(data.bytes()).release_value()) // FIXME: Handle possible OOM situation.
     {
     }
 

+ 9 - 6
Userland/Libraries/LibWebSocket/WebSocket.cpp

@@ -98,7 +98,7 @@ void WebSocket::close(u16 code, String message)
     VERIFY(m_state == WebSocket::InternalState::Open);
     VERIFY(m_impl);
     auto message_bytes = message.bytes();
-    auto close_payload = ByteBuffer::create_uninitialized(message_bytes.size() + 2);
+    auto close_payload = ByteBuffer::create_uninitialized(message_bytes.size() + 2).release_value(); // FIXME: Handle possible OOM situation.
     close_payload.overwrite(0, (u8*)&code, 2);
     close_payload.overwrite(2, message_bytes.data(), message_bytes.size());
     send_frame(WebSocket::OpCode::ConnectionClose, close_payload, true);
@@ -428,7 +428,7 @@ void WebSocket::read_frame()
         masking_key[3] = masking_key_data[3];
     }
 
-    auto payload = ByteBuffer::create_uninitialized(payload_length);
+    auto payload = ByteBuffer::create_uninitialized(payload_length).release_value(); // FIXME: Handle possible OOM situation.
     u64 read_length = 0;
     while (read_length < payload_length) {
         auto payload_part = m_impl->read(payload_length - read_length);
@@ -546,11 +546,14 @@ void WebSocket::send_frame(WebSocket::OpCode op_code, ReadonlyBytes payload, boo
         fill_with_random(masking_key, 4);
         m_impl->send(ReadonlyBytes(masking_key, 4));
         // Mask the payload
-        auto masked_payload = ByteBuffer::create_uninitialized(payload.size());
-        for (size_t i = 0; i < payload.size(); ++i) {
-            masked_payload[i] = payload[i] ^ (masking_key[i % 4]);
+        auto buffer_result = ByteBuffer::create_uninitialized(payload.size());
+        if (buffer_result.has_value()) {
+            auto& masked_payload = buffer_result.value();
+            for (size_t i = 0; i < payload.size(); ++i) {
+                masked_payload[i] = payload[i] ^ (masking_key[i % 4]);
+            }
+            m_impl->send(masked_payload);
         }
-        m_impl->send(masked_payload);
     } else {
         m_impl->send(payload);
     }

+ 1 - 1
Userland/Services/DHCPClient/DHCPv4.h

@@ -239,7 +239,7 @@ private:
 class DHCPv4PacketBuilder {
 public:
     DHCPv4PacketBuilder()
-        : m_buffer(ByteBuffer::create_zeroed(sizeof(DHCPv4Packet)))
+        : m_buffer(ByteBuffer::create_zeroed(sizeof(DHCPv4Packet)).release_value()) // FIXME: Handle possible OOM failure.
     {
         auto* options = peek().options();
         // set the magic DHCP cookie value

+ 5 - 1
Userland/Services/RequestServer/HttpCommon.h

@@ -69,7 +69,11 @@ OwnPtr<Request> start_request(TBadgedProtocol&& protocol, ClientConnection& clie
         request.set_method(HTTP::HttpRequest::Method::GET);
     request.set_url(url);
     request.set_headers(headers);
-    request.set_body(body);
+
+    auto allocated_body_result = ByteBuffer::copy(body);
+    if (!allocated_body_result.has_value())
+        return {};
+    request.set_body(allocated_body_result.release_value());
 
     auto output_stream = make<OutputFileStream>(pipe_result.value().write_fd);
     output_stream->make_unbuffered();

+ 2 - 2
Userland/Services/SpiceAgent/ClipboardServerConnection.cpp

@@ -38,8 +38,8 @@ RefPtr<Gfx::Bitmap> ClipboardServerConnection::get_bitmap()
     if (!format.has_value() || format.value() == 0)
         return nullptr;
 
-    auto data = ByteBuffer::copy(clipping.data().data<void>(), clipping.data().size());
-    auto clipping_bitmap = Gfx::Bitmap::try_create_wrapper((Gfx::BitmapFormat)format.value(), { (int)width.value(), (int)height.value() }, scale.value(), pitch.value(), data.data());
+    auto data = clipping.data().data<void>();
+    auto clipping_bitmap = Gfx::Bitmap::try_create_wrapper((Gfx::BitmapFormat)format.value(), { (int)width.value(), (int)height.value() }, scale.value(), pitch.value(), const_cast<void*>(data));
     auto bitmap = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, { (int)width.value(), (int)height.value() }, scale.value());
 
     for (int y = 0; y < clipping_bitmap->physical_height(); ++y) {

+ 13 - 11
Userland/Services/SpiceAgent/SpiceAgent.cpp

@@ -59,7 +59,7 @@ void SpiceAgent::on_message_received()
 {
     ChunkHeader header {};
     read_n(&header, sizeof(header));
-    auto buffer = ByteBuffer::create_uninitialized(header.size);
+    auto buffer = ByteBuffer::create_uninitialized(header.size).release_value(); // FIXME: Handle possible OOM situation.
     read_n(buffer.data(), buffer.size());
     auto* message = reinterpret_cast<Message*>(buffer.data());
     switch (message->type) {
@@ -75,15 +75,17 @@ void SpiceAgent::on_message_received()
         auto* request_message = reinterpret_cast<ClipboardRequest*>(message->data);
         auto clipboard = m_clipboard_connection.get_clipboard_data();
         auto& mime = clipboard.mime_type();
-        ByteBuffer byte_buffer;
+        ByteBuffer backing_byte_buffer;
+        ReadonlyBytes bytes;
         if (mime == "image/x-serenityos") {
             auto bitmap = m_clipboard_connection.get_bitmap();
-            byte_buffer = Gfx::PNGWriter::encode(*bitmap);
+            backing_byte_buffer = Gfx::PNGWriter::encode(*bitmap);
+            bytes = backing_byte_buffer;
         } else {
-            auto clip_data = clipboard.data();
-            byte_buffer = ByteBuffer::copy(clip_data.data<void>(), clip_data.size());
+            auto data = clipboard.data();
+            bytes = { data.data<void>(), data.size() };
         }
-        auto clipboard_buffer = Clipboard::make_buffer((ClipboardType)request_message->type, byte_buffer);
+        auto clipboard_buffer = Clipboard::make_buffer((ClipboardType)request_message->type, bytes);
         send_message(clipboard_buffer);
         break;
     }
@@ -116,7 +118,7 @@ void SpiceAgent::on_message_received()
     case (u32)MessageType::Clipboard: {
         auto* clipboard_message = reinterpret_cast<Clipboard*>(message->data);
         auto type = (ClipboardType)clipboard_message->type;
-        auto data_buffer = ByteBuffer::create_uninitialized(message->size - sizeof(u32));
+        auto data_buffer = ByteBuffer::create_uninitialized(message->size - sizeof(u32)).release_value(); // FIXME: Handle possible OOM situation.
 
         const auto total_bytes = message->size - sizeof(Clipboard);
         auto bytes_copied = header.size - sizeof(Message) - sizeof(Clipboard);
@@ -204,7 +206,7 @@ SpiceAgent::Message* SpiceAgent::initialize_headers(u8* data, size_t additional_
 ByteBuffer SpiceAgent::AnnounceCapabilities::make_buffer(bool request, const Vector<Capability>& capabilities)
 {
     size_t required_size = sizeof(ChunkHeader) + sizeof(Message) + sizeof(AnnounceCapabilities);
-    auto buffer = ByteBuffer::create_uninitialized(required_size);
+    auto buffer = ByteBuffer::create_uninitialized(required_size).release_value(); // FIXME: Handle possible OOM situation.
     u8* data = buffer.data();
 
     auto* message = initialize_headers(data, sizeof(AnnounceCapabilities), MessageType::AnnounceCapabilities);
@@ -226,7 +228,7 @@ ByteBuffer SpiceAgent::ClipboardGrab::make_buffer(const Vector<ClipboardType>& t
     VERIFY(types.size() > 0);
     size_t variable_data_size = sizeof(u32) * types.size();
     size_t required_size = sizeof(ChunkHeader) + sizeof(Message) + variable_data_size;
-    auto buffer = ByteBuffer::create_uninitialized(required_size);
+    auto buffer = ByteBuffer::create_uninitialized(required_size).release_value(); // FIXME: Handle possible OOM situation.
     u8* data = buffer.data();
 
     auto* message = initialize_headers(data, variable_data_size, MessageType::ClipboardGrab);
@@ -244,7 +246,7 @@ ByteBuffer SpiceAgent::Clipboard::make_buffer(ClipboardType type, ReadonlyBytes
 {
     size_t data_size = sizeof(Clipboard) + contents.size();
     size_t required_size = sizeof(ChunkHeader) + sizeof(Message) + data_size;
-    auto buffer = ByteBuffer::create_uninitialized(required_size);
+    auto buffer = ByteBuffer::create_uninitialized(required_size).release_value(); // FIXME: Handle possible OOM situation.
     u8* data = buffer.data();
 
     auto* message = initialize_headers(data, data_size, MessageType::Clipboard);
@@ -262,7 +264,7 @@ ByteBuffer SpiceAgent::ClipboardRequest::make_buffer(ClipboardType type)
 {
     size_t data_size = sizeof(ClipboardRequest);
     size_t required_size = sizeof(ChunkHeader) + sizeof(Message) + data_size;
-    auto buffer = ByteBuffer::create_uninitialized(required_size);
+    auto buffer = ByteBuffer::create_uninitialized(required_size).release_value(); // FIXME: Handle possible OOM situation.
     u8* data = buffer.data();
 
     auto* message = initialize_headers(data, data_size, MessageType::ClipboardRequest);

+ 1 - 1
Userland/Services/TelnetServer/Client.cpp

@@ -150,7 +150,7 @@ void Client::send_command(Command command)
 
 void Client::send_commands(Vector<Command> commands)
 {
-    auto buffer = ByteBuffer::create_uninitialized(commands.size() * 3);
+    auto buffer = ByteBuffer::create_uninitialized(commands.size() * 3).release_value(); // FIXME: Handle possible OOM situation.
     OutputMemoryStream stream { buffer };
 
     for (auto& command : commands)

+ 13 - 2
Userland/Shell/AST.cpp

@@ -1589,7 +1589,13 @@ void Execute::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Non
                             return Break;
                         }
                 } else {
-                    auto entry = ByteBuffer::create_uninitialized(line_end + ifs.length());
+                    auto entry_result = ByteBuffer::create_uninitialized(line_end + ifs.length());
+                    if (!entry_result.has_value()) {
+                        loop.quit(Break);
+                        notifier->set_enabled(false);
+                        return Break;
+                    }
+                    auto entry = entry_result.release_value();
                     auto rc = stream.read_or_error(entry);
                     VERIFY(rc);
 
@@ -1675,7 +1681,12 @@ void Execute::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Non
             } while (action == Continue);
 
             if (!stream.eof()) {
-                auto entry = ByteBuffer::create_uninitialized(stream.size());
+                auto entry_result = ByteBuffer::create_uninitialized(stream.size());
+                if (!entry_result.has_value()) {
+                    shell->raise_error(Shell::ShellError::OutOfMemory, {}, position());
+                    return;
+                }
+                auto entry = entry_result.release_value();
                 auto rc = stream.read_or_error(entry);
                 VERIFY(rc);
                 callback(make_ref_counted<StringValue>(String::copy(entry)));

+ 3 - 0
Userland/Shell/Shell.cpp

@@ -1999,6 +1999,9 @@ void Shell::possibly_print_error() const
     case ShellError::OpenFailure:
         warnln("Shell: Open failed for {}", m_error_description);
         break;
+    case ShellError::OutOfMemory:
+        warnln("Shell: Hit an OOM situation");
+        break;
     case ShellError::InternalControlFlowBreak:
     case ShellError::InternalControlFlowContinue:
         return;

+ 1 - 0
Userland/Shell/Shell.h

@@ -233,6 +233,7 @@ public:
         InvalidGlobError,
         InvalidSliceContentsError,
         OpenFailure,
+        OutOfMemory,
     };
 
     void raise_error(ShellError kind, String description, Optional<AST::Position> position = {})

部分文件因文件數量過多而無法顯示