diff --git a/Libraries/LibCore/AnonymousBuffer.cpp b/Libraries/LibCore/AnonymousBuffer.cpp index f009ab0cefb..b75a08e1118 100644 --- a/Libraries/LibCore/AnonymousBuffer.cpp +++ b/Libraries/LibCore/AnonymousBuffer.cpp @@ -20,9 +20,13 @@ ErrorOr AnonymousBuffer::create_with_size(size_t size) ErrorOr> AnonymousBufferImpl::create(int fd, size_t size) { - auto* data = mmap(nullptr, round_up_to_power_of_two(size, PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) - return Error::from_errno(errno); + void* data = nullptr; + // POSIX mmap rejects a zero length with EINVAL, so leave m_data null for zero-size buffers. + if (size > 0) { + data = mmap(nullptr, round_up_to_power_of_two(size, PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) + return Error::from_errno(errno); + } return AK::adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousBufferImpl(fd, size, data)); } @@ -32,8 +36,10 @@ AnonymousBufferImpl::~AnonymousBufferImpl() auto rc = close(m_fd); VERIFY(rc == 0); } - auto rc = munmap(m_data, round_up_to_power_of_two(m_size, PAGE_SIZE)); - VERIFY(rc == 0); + if (m_data) { + auto rc = munmap(m_data, round_up_to_power_of_two(m_size, PAGE_SIZE)); + VERIFY(rc == 0); + } } ErrorOr AnonymousBuffer::create_from_anon_fd(int fd, size_t size) diff --git a/Libraries/LibCore/AnonymousBufferWindows.cpp b/Libraries/LibCore/AnonymousBufferWindows.cpp index d13b5fe7431..912f0c45afc 100644 --- a/Libraries/LibCore/AnonymousBufferWindows.cpp +++ b/Libraries/LibCore/AnonymousBufferWindows.cpp @@ -30,7 +30,10 @@ AnonymousBufferImpl::~AnonymousBufferImpl() ErrorOr> AnonymousBufferImpl::create(size_t size) { - HANDLE map_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, size >> 32, size & 0xFFFFFFFF, NULL); + // CreateFileMapping rejects a zero-size mapping backed by INVALID_HANDLE_VALUE, so allocate at least one byte and + // track the logical size separately. + auto map_size = max(size, 1uz); + HANDLE map_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, map_size >> 32, map_size & 0xFFFFFFFF, NULL); if (!map_handle) return Error::from_windows_error(); @@ -39,9 +42,12 @@ ErrorOr> AnonymousBufferImpl::create(size_t s ErrorOr> AnonymousBufferImpl::create(int fd, size_t size) { - void* ptr = MapViewOfFile(to_handle(fd), FILE_MAP_ALL_ACCESS, 0, 0, size); - if (!ptr) - return Error::from_windows_error(); + void* ptr = nullptr; + if (size > 0) { + ptr = MapViewOfFile(to_handle(fd), FILE_MAP_ALL_ACCESS, 0, 0, size); + if (!ptr) + return Error::from_windows_error(); + } return adopt_ref(*new AnonymousBufferImpl(fd, size, ptr)); } diff --git a/Services/WebContent/ConnectionFromClient.cpp b/Services/WebContent/ConnectionFromClient.cpp index b6950ac44c5..bdb0826b8b9 100644 --- a/Services/WebContent/ConnectionFromClient.cpp +++ b/Services/WebContent/ConnectionFromClient.cpp @@ -1070,7 +1070,8 @@ void ConnectionFromClient::request_internal_page_info(u64 page_id, WebView::Page } auto buffer = MUST(Core::AnonymousBuffer::create_with_size(builder.length())); - memcpy(buffer.data(), builder.string_view().characters_without_null_termination(), builder.length()); + if (builder.length() > 0) + memcpy(buffer.data(), builder.string_view().characters_without_null_termination(), builder.length()); async_did_get_internal_page_info(page_id, type, buffer); } diff --git a/Tests/LibCore/TestLibCoreAnonymousBuffer.cpp b/Tests/LibCore/TestLibCoreAnonymousBuffer.cpp index 482d7cc7540..031c211f8af 100644 --- a/Tests/LibCore/TestLibCoreAnonymousBuffer.cpp +++ b/Tests/LibCore/TestLibCoreAnonymousBuffer.cpp @@ -42,6 +42,20 @@ TEST_CASE(read_and_write_contents) EXPECT_EQ(read_back, payload); } +TEST_CASE(create_with_zero_size) +{ + auto buffer = MUST(Core::AnonymousBuffer::create_with_size(0)); + EXPECT(buffer.is_valid()); + EXPECT_EQ(buffer.size(), 0u); + EXPECT(buffer.bytes().is_empty()); + + auto fd = MUST(Core::System::dup(buffer.fd())); + auto mirror = MUST(Core::AnonymousBuffer::create_from_anon_fd(fd, 0)); + EXPECT(mirror.is_valid()); + EXPECT_EQ(mirror.size(), 0u); + EXPECT(mirror.bytes().is_empty()); +} + TEST_CASE(reconstruct_from_anon_fd_shares_memory) { auto original = MUST(Core::AnonymousBuffer::create_with_size(128));