1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:47:46 +00:00

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.
This commit is contained in:
Andreas Kling 2021-01-16 11:12:59 +01:00
parent 1a157d3f50
commit f18d89b36d

View file

@ -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;
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;
}
};
const auto pitch = minimum_pitch(size.width(), format);
const auto data_size_in_bytes = size_in_bytes(pitch, size.height());
if (size_would_overflow(format, size))
return nullptr;
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;
}
const auto pitch = minimum_pitch(size.width(), format);
const auto data_size_in_bytes = size_in_bytes(pitch, size.height());
if (should_close_anon_fd == ShouldCloseAnonymousFile::Yes) {
int rc = close(anon_fd);
ASSERT(rc == 0);
anon_fd = -1;
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));