From 13b94f282bf526814d091ccbb66fc5842e9dda24 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Fri, 22 Mar 2024 11:21:31 +0100 Subject: [PATCH] Correctly handle failing mmap on FileReader. If we try to mmap a region to high (>4GB), `makeMmappedBuffer` will throw a `MMapException`. In this case, we want to do a read in the file instead of mmap. This case is handled in `MultiPartFileReader` but was missing in `FileReader`. Fix #866 --- src/file_reader.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/file_reader.cpp b/src/file_reader.cpp index 2fcf09661..bb5d446a8 100644 --- a/src/file_reader.cpp +++ b/src/file_reader.cpp @@ -201,7 +201,10 @@ const Buffer MultiPartFileReader::get_buffer(offset_t offset, zsize_t size) cons } catch(MMapException& e) #endif { - // The range is several part, or we are on Windows. + // We cannot do the mmap, for several possible reasons: + // - Mmap offset is too big (>4GB on 32 bits) + // - The range is several part + // - We are on Windows. // We will have to do some memory copies :/ // [TODO] Use Windows equivalent for mmap. auto ret_buffer = Buffer::makeBuffer(size); @@ -278,14 +281,22 @@ const Buffer FileReader::get_buffer(offset_t offset, zsize_t size) const { ASSERT(size, <=, _size); #ifdef ENABLE_USE_MMAP - offset += _offset; - int fd = _fhandle->getNativeHandle(); - return Buffer::makeBuffer(makeMmappedBuffer(fd, offset, size), size); -#else // We are on Windows. [TODO] Use Windows equivalent for mmap. - auto ret_buffer = Buffer::makeBuffer(size); - read(const_cast(ret_buffer.data()), offset, size); - return ret_buffer; + try { + auto local_offset = offset + _offset; + int fd = _fhandle->getNativeHandle(); + return Buffer::makeBuffer(makeMmappedBuffer(fd, local_offset, size), size); + } catch(MMapException& e) #endif + { + // We cannot do the mmap, for several possible reasons: + // - Mmap offset is too big (>4GB on 32 bits) + // - We are on Windows. + // We will have to do some memory copies :/ + // [TODO] Use Windows equivalent for mmap. + auto ret_buffer = Buffer::makeBuffer(size); + read(const_cast(ret_buffer.data()), offset, size); + return ret_buffer; + } } std::unique_ptr