Index: libtorrent/src/data/socket_file.cc =================================================================== --- libtorrent/src/data/socket_file.cc (revision 827) +++ libtorrent/src/data/socket_file.cc (working copy) @@ -162,20 +162,27 @@ MemoryChunk SocketFile::create_chunk(uint64_t offset, uint32_t length, int prot, int flags) const { if (!is_open()) - throw internal_error("SocketFile::get_chunk() called on a closed file"); + throw internal_error("SocketFile::get_chunk() called on a closed file."); if (((prot & MemoryChunk::prot_read) && !is_readable()) || ((prot & MemoryChunk::prot_write) && !is_writable())) - throw storage_error("SocketFile::get_chunk() permission denied"); + throw storage_error("SocketFile::get_chunk() permission denied."); + uint64_t fileSize = size(); + // For some reason mapping beyond the extent of the file does not // cause mmap to complain, so we need to check manually here. - if (offset < 0 || length == 0 || offset > size() || offset + length > size()) + if (offset < 0 || length == 0 || offset > fileSize || offset + length > fileSize) return MemoryChunk(); - uint64_t align = offset % MemoryChunk::page_size(); + uint64_t align = offset % MemoryChunk::page_size(); + uint64_t mapLength = std::min(((length + align + MemoryChunk::page_size() - 1) / MemoryChunk::page_size()) * MemoryChunk::page_size(), + fileSize - (offset - align)); - char* ptr = (char*)mmap(NULL, length + align, prot, flags, m_fd, offset - align); + if (offset - align + mapLength != fileSize && (offset - align + mapLength) % MemoryChunk::page_size() != 0) + throw internal_error("SocketFile::create_chunk(...) Length not page aligned."); + + char* ptr = (char*)mmap(NULL, mapLength, prot, flags, m_fd, offset - align); if (ptr == MAP_FAILED) return MemoryChunk();