Merge pull request #30190 from azat/ReadBuffer-throw-on-empty

Do not allow zero-length reads
This commit is contained in:
alexey-milovidov 2021-11-17 10:21:08 +03:00 committed by GitHub
commit 1e058fb207
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 0 deletions

View File

@ -0,0 +1,23 @@
#pragma once
#include <IO/ReadBuffer.h>
namespace DB
{
/// In case of empty file it does not make any sense to read it.
///
/// Plus regular readers from file has an assert that buffer is not empty, that will fail:
/// - ReadBufferFromFileDescriptor
/// - SynchronousReader
/// - ThreadPoolReader
class ReadBufferFromEmptyFile : public ReadBufferFromFileBase
{
private:
bool nextImpl() override { return false; }
std::string getFileName() const override { return "<empty>"; }
off_t seek(off_t /*off*/, int /*whence*/) override { return 0; }
off_t getPosition() override { return 0; }
};
}

View File

@ -51,6 +51,9 @@ std::string ReadBufferFromFileDescriptor::getFileName() const
bool ReadBufferFromFileDescriptor::nextImpl()
{
/// If internal_buffer size is empty, then read() cannot be distinguished from EOF
assert(!internal_buffer.empty());
size_t bytes_read = 0;
while (!bytes_read)
{

View File

@ -36,6 +36,9 @@ namespace ErrorCodes
std::future<IAsynchronousReader::Result> SynchronousReader::submit(Request request)
{
/// If size is zero, then read() cannot be distinguished from EOF
assert(request.size);
int fd = assert_cast<const LocalFileDescriptor &>(*request.descriptor).fd;
#if defined(POSIX_FADV_WILLNEED)

View File

@ -76,6 +76,9 @@ ThreadPoolReader::ThreadPoolReader(size_t pool_size, size_t queue_size_)
std::future<IAsynchronousReader::Result> ThreadPoolReader::submit(Request request)
{
/// If size is zero, then read() cannot be distinguished from EOF
assert(request.size);
int fd = assert_cast<const LocalFileDescriptor &>(*request.descriptor).fd;
#if defined(__linux__)

View File

@ -1,4 +1,5 @@
#include <IO/createReadBufferFromFileBase.h>
#include <IO/ReadBufferFromEmptyFile.h>
#include <IO/ReadBufferFromFile.h>
#include <IO/MMapReadBufferFromFileWithCache.h>
#include <IO/AsynchronousReadBufferFromFile.h>
@ -33,6 +34,8 @@ std::unique_ptr<ReadBufferFromFileBase> createReadBufferFromFileBase(
char * existing_memory,
size_t alignment)
{
if (size.has_value() && !*size)
return std::make_unique<ReadBufferFromEmptyFile>();
size_t estimated_size = size.has_value() ? *size : 0;
if (!existing_memory

View File

@ -71,6 +71,9 @@ MergeTreeReaderCompact::MergeTreeReaderCompact(
if (buffer_size)
settings.read_settings = settings.read_settings.adjustBufferSize(buffer_size);
if (!settings.read_settings.local_fs_buffer_size || !settings.read_settings.remote_fs_buffer_size)
throw Exception(ErrorCodes::CANNOT_READ_ALL_DATA, "Cannot read to empty buffer.");
const String full_data_path = data_part->getFullRelativePath() + MergeTreeDataPartCompact::DATA_FILE_NAME_WITH_EXTENSION;
if (uncompressed_cache)
{