Fix segfault

This commit is contained in:
Ivan Lezhankin 2021-03-19 23:29:01 +03:00
parent 2303f1788c
commit 957c053f7e
4 changed files with 29 additions and 12 deletions

View File

@ -82,6 +82,7 @@ bool PeekableReadBuffer::peekNext()
checkpoint.emplace(memory.data());
checkpoint_in_own_memory = true;
}
if (currentlyReadFromOwnMemory())
{
/// Update buffer size
@ -99,7 +100,6 @@ bool PeekableReadBuffer::peekNext()
pos_offset = 0;
}
BufferBase::set(memory.data(), peeked_size + bytes_to_copy, pos_offset);
}
peeked_size += bytes_to_copy;
@ -113,12 +113,21 @@ void PeekableReadBuffer::rollbackToCheckpoint(bool drop)
{
checkStateCorrect();
if (!checkpoint)
throw DB::Exception("There is no checkpoint", ErrorCodes::LOGICAL_ERROR);
else if (checkpointInOwnMemory() == currentlyReadFromOwnMemory())
assert(checkpoint);
if (checkpointInOwnMemory() == currentlyReadFromOwnMemory())
{
/// Both checkpoint and position are in the same buffer.
pos = *checkpoint;
else /// Checkpoint is in own memory and pos is not. Switch to reading from own memory
}
else
{
/// Checkpoint is in own memory and position is not.
assert(checkpointInOwnMemory());
/// Switch to reading from own memory.
BufferBase::set(memory.data(), peeked_size, *checkpoint - memory.data());
}
if (drop)
dropCheckpoint();
@ -134,10 +143,11 @@ bool PeekableReadBuffer::nextImpl()
checkStateCorrect();
bool res;
bool checkpoint_at_end = checkpoint && *checkpoint == working_buffer.end();
if (checkpoint)
{
if (currentlyReadFromOwnMemory())
if (currentlyReadFromOwnMemory() || checkpoint_at_end)
res = sub_buf.hasPendingData() || sub_buf.next();
else
res = peekNext();
@ -163,6 +173,13 @@ bool PeekableReadBuffer::nextImpl()
BufferBase::set(sub_working.begin(), sub_working.size(), sub_buf.offset());
nextimpl_working_buffer_offset = sub_buf.offset();
if (checkpoint_at_end)
{
checkpoint.emplace(working_buffer.begin());
peeked_size = 0;
checkpoint_in_own_memory = false;
}
checkStateCorrect();
return res;
}

View File

@ -43,10 +43,7 @@ public:
/// Forget checkpoint and all data between checkpoint and position
ALWAYS_INLINE inline void dropCheckpoint()
{
#ifndef NDEBUG
if (!checkpoint)
throw DB::Exception("There is no checkpoint", ErrorCodes::LOGICAL_ERROR);
#endif
assert(checkpoint);
if (!currentlyReadFromOwnMemory())
{
/// Don't need to store unread data anymore

View File

@ -9,8 +9,6 @@
#include <Common/ActionBlocker.h>
#include <common/types.h>
#include <Poco/Net/HTMLForm.h>
#include <atomic>
#include <map>
#include <shared_mutex>

View File

@ -369,6 +369,11 @@ bool HTMLForm::MultipartReadBuffer::nextImpl()
else
boundary_hit = startsWith(line, boundary);
if (!line.empty())
/// If we don't make sure that memory is contiguous then situation may happen, when part of the line is inside internal memory
/// and other part is inside sub-buffer, thus we'll be unable to setup our working buffer properly.
in.makeContinuousMemoryFromCheckpointToPos();
in.rollbackToCheckpoint(true);
/// Rolling back to checkpoint may change underlying buffers.