mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-12 14:46:08 +00:00
Add a BufferConsumer primitive for wire [de]serialization
BufferConsumer wraps a buffer pointer and size and exposes a limited number of operations to get data while decrementing the remaining available size. This makes it so that code reading or writing into a buffer cannot easily consume more bytes than available. This CL guards against serialization overflows using BufferConsumer, and it implements GetPtrFromBuffer (for deserialization) on top of BufferConsumer. A future patch will make the rest of the deserialization code use BufferConsumer. Bug: dawn:680 Change-Id: Ic2bd6e7039e83ce70307c2ff47aaca9891c16d91 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/41780 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Stephen White <senorblanco@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
eb71aaf689
commit
1b31dc0bb2
@@ -63,6 +63,7 @@ dawn_component("dawn_wire") {
|
||||
"ChunkedCommandHandler.h",
|
||||
"ChunkedCommandSerializer.cpp",
|
||||
"ChunkedCommandSerializer.h",
|
||||
"Wire.cpp",
|
||||
"WireClient.cpp",
|
||||
"WireDeserializeAllocator.cpp",
|
||||
"WireDeserializeAllocator.h",
|
||||
|
||||
@@ -35,6 +35,7 @@ target_sources(dawn_wire PRIVATE
|
||||
"ChunkedCommandHandler.h"
|
||||
"ChunkedCommandSerializer.cpp"
|
||||
"ChunkedCommandSerializer.h"
|
||||
"Wire.cpp"
|
||||
"WireClient.cpp"
|
||||
"WireDeserializeAllocator.cpp"
|
||||
"WireDeserializeAllocator.h"
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace dawn_wire {
|
||||
|
||||
template <typename Cmd>
|
||||
void SerializeCommand(const Cmd& cmd) {
|
||||
SerializeCommand(cmd, 0, [](char*) {});
|
||||
SerializeCommand(cmd, 0, [](SerializeBuffer*) { return true; });
|
||||
}
|
||||
|
||||
template <typename Cmd, typename ExtraSizeSerializeFn>
|
||||
@@ -41,15 +41,15 @@ namespace dawn_wire {
|
||||
ExtraSizeSerializeFn&& SerializeExtraSize) {
|
||||
SerializeCommandImpl(
|
||||
cmd,
|
||||
[](const Cmd& cmd, size_t requiredSize, char* allocatedBuffer) {
|
||||
cmd.Serialize(requiredSize, allocatedBuffer);
|
||||
[](const Cmd& cmd, size_t requiredSize, SerializeBuffer* serializeBuffer) {
|
||||
return cmd.Serialize(requiredSize, serializeBuffer);
|
||||
},
|
||||
extraSize, std::forward<ExtraSizeSerializeFn>(SerializeExtraSize));
|
||||
}
|
||||
|
||||
template <typename Cmd>
|
||||
void SerializeCommand(const Cmd& cmd, const ObjectIdProvider& objectIdProvider) {
|
||||
SerializeCommand(cmd, objectIdProvider, 0, [](char*) {});
|
||||
SerializeCommand(cmd, objectIdProvider, 0, [](SerializeBuffer*) { return true; });
|
||||
}
|
||||
|
||||
template <typename Cmd, typename ExtraSizeSerializeFn>
|
||||
@@ -59,8 +59,9 @@ namespace dawn_wire {
|
||||
ExtraSizeSerializeFn&& SerializeExtraSize) {
|
||||
SerializeCommandImpl(
|
||||
cmd,
|
||||
[&objectIdProvider](const Cmd& cmd, size_t requiredSize, char* allocatedBuffer) {
|
||||
cmd.Serialize(requiredSize, allocatedBuffer, objectIdProvider);
|
||||
[&objectIdProvider](const Cmd& cmd, size_t requiredSize,
|
||||
SerializeBuffer* serializeBuffer) {
|
||||
return cmd.Serialize(requiredSize, serializeBuffer, objectIdProvider);
|
||||
},
|
||||
extraSize, std::forward<ExtraSizeSerializeFn>(SerializeExtraSize));
|
||||
}
|
||||
@@ -77,8 +78,13 @@ namespace dawn_wire {
|
||||
if (requiredSize <= mMaxAllocationSize) {
|
||||
char* allocatedBuffer = static_cast<char*>(mSerializer->GetCmdSpace(requiredSize));
|
||||
if (allocatedBuffer != nullptr) {
|
||||
SerializeCmd(cmd, requiredSize, allocatedBuffer);
|
||||
SerializeExtraSize(allocatedBuffer + commandSize);
|
||||
SerializeBuffer serializeBuffer(allocatedBuffer, requiredSize);
|
||||
bool success = true;
|
||||
success &= SerializeCmd(cmd, requiredSize, &serializeBuffer);
|
||||
success &= SerializeExtraSize(&serializeBuffer);
|
||||
if (DAWN_UNLIKELY(!success)) {
|
||||
mSerializer->OnSerializeError();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -87,8 +93,14 @@ namespace dawn_wire {
|
||||
if (!cmdSpace) {
|
||||
return;
|
||||
}
|
||||
SerializeCmd(cmd, requiredSize, cmdSpace.get());
|
||||
SerializeExtraSize(cmdSpace.get() + commandSize);
|
||||
SerializeBuffer serializeBuffer(cmdSpace.get(), requiredSize);
|
||||
bool success = true;
|
||||
success &= SerializeCmd(cmd, requiredSize, &serializeBuffer);
|
||||
success &= SerializeExtraSize(&serializeBuffer);
|
||||
if (DAWN_UNLIKELY(!success)) {
|
||||
mSerializer->OnSerializeError();
|
||||
return;
|
||||
}
|
||||
SerializeChunkedCommand(cmdSpace.get(), requiredSize);
|
||||
}
|
||||
|
||||
|
||||
26
src/dawn_wire/Wire.cpp
Normal file
26
src/dawn_wire/Wire.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2021 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dawn_wire/Wire.h"
|
||||
|
||||
namespace dawn_wire {
|
||||
|
||||
CommandSerializer::~CommandSerializer() = default;
|
||||
|
||||
void CommandSerializer::OnSerializeError() {
|
||||
}
|
||||
|
||||
CommandHandler::~CommandHandler() = default;
|
||||
|
||||
} // namespace dawn_wire
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "dawn_wire/client/Buffer.h"
|
||||
|
||||
#include "dawn_wire/WireCmd_autogen.h"
|
||||
#include "dawn_wire/client/Client.h"
|
||||
#include "dawn_wire/client/Device.h"
|
||||
|
||||
@@ -73,19 +74,24 @@ namespace dawn_wire { namespace client {
|
||||
cmd.handleCreateInfoLength = writeHandleCreateInfoLength;
|
||||
cmd.handleCreateInfo = nullptr;
|
||||
|
||||
wireClient->SerializeCommand(cmd, writeHandleCreateInfoLength, [&](char* cmdSpace) {
|
||||
if (descriptor->mappedAtCreation) {
|
||||
// Serialize the WriteHandle into the space after the command.
|
||||
writeHandle->SerializeCreate(cmdSpace);
|
||||
wireClient->SerializeCommand(
|
||||
cmd, writeHandleCreateInfoLength, [&](SerializeBuffer* serializeBuffer) {
|
||||
if (descriptor->mappedAtCreation) {
|
||||
if (serializeBuffer->AvailableSize() != writeHandleCreateInfoLength) {
|
||||
return false;
|
||||
}
|
||||
// Serialize the WriteHandle into the space after the command.
|
||||
writeHandle->SerializeCreate(serializeBuffer->Buffer());
|
||||
|
||||
// Set the buffer state for the mapping at creation. The buffer now owns the write
|
||||
// handle..
|
||||
buffer->mWriteHandle = std::move(writeHandle);
|
||||
buffer->mMappedData = writeData;
|
||||
buffer->mMapOffset = 0;
|
||||
buffer->mMapSize = buffer->mSize;
|
||||
}
|
||||
});
|
||||
// Set the buffer state for the mapping at creation. The buffer now owns the
|
||||
// write handle..
|
||||
buffer->mWriteHandle = std::move(writeHandle);
|
||||
buffer->mMappedData = writeData;
|
||||
buffer->mMapOffset = 0;
|
||||
buffer->mMapSize = buffer->mSize;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return ToAPI(buffer);
|
||||
}
|
||||
|
||||
@@ -199,15 +205,25 @@ namespace dawn_wire { namespace client {
|
||||
// Step 3a. Fill the handle create info in the command.
|
||||
if (isReadMode) {
|
||||
cmd.handleCreateInfoLength = request.readHandle->SerializeCreateSize();
|
||||
client->SerializeCommand(cmd, cmd.handleCreateInfoLength, [&](char* cmdSpace) {
|
||||
request.readHandle->SerializeCreate(cmdSpace);
|
||||
});
|
||||
client->SerializeCommand(
|
||||
cmd, cmd.handleCreateInfoLength, [&](SerializeBuffer* serializeBuffer) {
|
||||
bool success = serializeBuffer->AvailableSize() == cmd.handleCreateInfoLength;
|
||||
if (success) {
|
||||
request.readHandle->SerializeCreate(serializeBuffer->Buffer());
|
||||
}
|
||||
return success;
|
||||
});
|
||||
} else {
|
||||
ASSERT(isWriteMode);
|
||||
cmd.handleCreateInfoLength = request.writeHandle->SerializeCreateSize();
|
||||
client->SerializeCommand(cmd, cmd.handleCreateInfoLength, [&](char* cmdSpace) {
|
||||
request.writeHandle->SerializeCreate(cmdSpace);
|
||||
});
|
||||
client->SerializeCommand(
|
||||
cmd, cmd.handleCreateInfoLength, [&](SerializeBuffer* serializeBuffer) {
|
||||
bool success = serializeBuffer->AvailableSize() == cmd.handleCreateInfoLength;
|
||||
if (success) {
|
||||
request.writeHandle->SerializeCreate(serializeBuffer->Buffer());
|
||||
}
|
||||
return success;
|
||||
});
|
||||
}
|
||||
|
||||
// Step 4. Register this request so that we can retrieve it from its serial when the server
|
||||
@@ -334,11 +350,16 @@ namespace dawn_wire { namespace client {
|
||||
cmd.writeFlushInfoLength = writeFlushInfoLength;
|
||||
cmd.writeFlushInfo = nullptr;
|
||||
|
||||
client->SerializeCommand(cmd, writeFlushInfoLength, [&](char* cmdSpace) {
|
||||
// Serialize flush metadata into the space after the command.
|
||||
// This closes the handle for writing.
|
||||
mWriteHandle->SerializeFlush(cmdSpace);
|
||||
});
|
||||
client->SerializeCommand(
|
||||
cmd, writeFlushInfoLength, [&](SerializeBuffer* serializeBuffer) {
|
||||
bool success = serializeBuffer->AvailableSize() == writeFlushInfoLength;
|
||||
if (success) {
|
||||
// Serialize flush metadata into the space after the command.
|
||||
// This closes the handle for writing.
|
||||
mWriteHandle->SerializeFlush(serializeBuffer->Buffer());
|
||||
}
|
||||
return success;
|
||||
});
|
||||
mWriteHandle = nullptr;
|
||||
|
||||
} else if (mReadHandle) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "common/Assert.h"
|
||||
#include "dawn_wire/WireCmd_autogen.h"
|
||||
#include "dawn_wire/server/Server.h"
|
||||
|
||||
#include <memory>
|
||||
@@ -242,11 +243,15 @@ namespace dawn_wire { namespace server {
|
||||
data->readHandle->SerializeInitialDataSize(readData, data->size);
|
||||
}
|
||||
|
||||
SerializeCommand(cmd, cmd.readInitialDataInfoLength, [&](char* cmdSpace) {
|
||||
SerializeCommand(cmd, cmd.readInitialDataInfoLength, [&](SerializeBuffer* serializeBuffer) {
|
||||
if (isSuccess) {
|
||||
if (isRead) {
|
||||
if (serializeBuffer->AvailableSize() != cmd.readInitialDataInfoLength) {
|
||||
return false;
|
||||
}
|
||||
// Serialize the initialization message into the space after the command.
|
||||
data->readHandle->SerializeInitialData(readData, data->size, cmdSpace);
|
||||
data->readHandle->SerializeInitialData(readData, data->size,
|
||||
serializeBuffer->Buffer());
|
||||
// The in-flight map request returned successfully.
|
||||
// Move the ReadHandle so it is owned by the buffer.
|
||||
bufferData->readHandle = std::move(data->readHandle);
|
||||
@@ -261,6 +266,7 @@ namespace dawn_wire { namespace server {
|
||||
data->size);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace dawn_wire {
|
||||
|
||||
class DAWN_WIRE_EXPORT CommandSerializer {
|
||||
public:
|
||||
virtual ~CommandSerializer() = default;
|
||||
virtual ~CommandSerializer();
|
||||
|
||||
// Get space for serializing commands.
|
||||
// GetCmdSpace will never be called with a value larger than
|
||||
@@ -34,11 +34,12 @@ namespace dawn_wire {
|
||||
virtual void* GetCmdSpace(size_t size) = 0;
|
||||
virtual bool Flush() = 0;
|
||||
virtual size_t GetMaximumAllocationSize() const = 0;
|
||||
virtual void OnSerializeError();
|
||||
};
|
||||
|
||||
class DAWN_WIRE_EXPORT CommandHandler {
|
||||
public:
|
||||
virtual ~CommandHandler() = default;
|
||||
virtual ~CommandHandler();
|
||||
virtual const volatile char* HandleCommands(const volatile char* commands, size_t size) = 0;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user