summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-16 11:12:59 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-16 11:26:53 +0100
commitf18d89b36d6762324af8ff420230b409efd95d81 (patch)
tree20d5940cb3396bfaea3e0d2cc3de190f0aea8e8e
parent1a157d3f50f9144e5e730f6dd4f97288a7c8f781 (diff)
downloadserenity-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.cpp39
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));