diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-16 11:12:59 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-16 11:26:53 +0100 |
commit | f18d89b36d6762324af8ff420230b409efd95d81 (patch) | |
tree | 20d5940cb3396bfaea3e0d2cc3de190f0aea8e8e | |
parent | 1a157d3f50f9144e5e730f6dd4f97288a7c8f781 (diff) | |
download | serenity-f18d89b36d6762324af8ff420230b409efd95d81.zip |
LibGfx: Make sure Bitmap::create_with_anon_fd() always closes if needed
If this is called with ShouldCloseAnonymousFile::Yes, it's entrusted
with closing the anon_fd and nobody else will take care of it.
-rw-r--r-- | Userland/Libraries/LibGfx/Bitmap.cpp | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/Userland/Libraries/LibGfx/Bitmap.cpp b/Userland/Libraries/LibGfx/Bitmap.cpp index d04f9801bb..5de2da2062 100644 --- a/Userland/Libraries/LibGfx/Bitmap.cpp +++ b/Userland/Libraries/LibGfx/Bitmap.cpp @@ -28,6 +28,7 @@ #include <AK/Memory.h> #include <AK/MemoryStream.h> #include <AK/Optional.h> +#include <AK/ScopeGuard.h> #include <AK/SharedBuffer.h> #include <AK/String.h> #include <LibGfx/BMPLoader.h> @@ -188,22 +189,28 @@ static bool check_size(const IntSize& size, BitmapFormat format, unsigned actual RefPtr<Bitmap> Bitmap::create_with_anon_fd(BitmapFormat format, int anon_fd, const IntSize& size, ShouldCloseAnonymousFile should_close_anon_fd) { - if (size_would_overflow(format, size)) - return nullptr; - - const auto pitch = minimum_pitch(size.width(), format); - const auto data_size_in_bytes = size_in_bytes(pitch, size.height()); - - auto* data = mmap(nullptr, round_up_to_power_of_two(data_size_in_bytes, PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, anon_fd, 0); - if (data == MAP_FAILED) { - perror("mmap"); - return nullptr; - } - - if (should_close_anon_fd == ShouldCloseAnonymousFile::Yes) { - int rc = close(anon_fd); - ASSERT(rc == 0); - anon_fd = -1; + void* data = nullptr; + { + // If ShouldCloseAnonymousFile::Yes, it's our responsibility to close 'anon_fd' no matter what. + ScopeGuard close_guard = [&] { + if (should_close_anon_fd == ShouldCloseAnonymousFile::Yes) { + int rc = close(anon_fd); + ASSERT(rc == 0); + anon_fd = -1; + } + }; + + if (size_would_overflow(format, size)) + return nullptr; + + const auto pitch = minimum_pitch(size.width(), format); + const auto data_size_in_bytes = size_in_bytes(pitch, size.height()); + + data = mmap(nullptr, round_up_to_power_of_two(data_size_in_bytes, PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, anon_fd, 0); + if (data == MAP_FAILED) { + perror("mmap"); + return nullptr; + } } return adopt(*new Bitmap(format, anon_fd, size, data)); |