Always point to own members in FlatComputePipelineDescriptor

This patch fixes a use-after-free issue in FlatComputePipelineDescriptor
by always making its pointer members point to its own members.

BUG=dawn:529, chromium:1246158, chromium:1246748
TEST=dawn_end2end_tests

Change-Id: I49b98357444edcdb1b225e961d1e4d6e5b11e978
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/63366
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Jiawei Shao 2021-09-06 07:46:49 +00:00 committed by Dawn LUCI CQ
parent 2e40f90e8c
commit ba1feb07bc
2 changed files with 40 additions and 6 deletions

View File

@ -28,15 +28,15 @@ namespace dawn_native {
// TODO(dawn:800): Remove after deprecation period. // TODO(dawn:800): Remove after deprecation period.
if (descriptor->compute.module == nullptr && descriptor->computeStage.module != nullptr) { if (descriptor->compute.module == nullptr && descriptor->computeStage.module != nullptr) {
compute.module = descriptor->computeStage.module; mComputeModule = descriptor->computeStage.module;
compute.entryPoint = descriptor->computeStage.entryPoint; mEntryPoint = descriptor->computeStage.entryPoint;
} else { } else {
compute.module = descriptor->compute.module; mComputeModule = descriptor->compute.module;
compute.entryPoint = descriptor->compute.entryPoint; mEntryPoint = descriptor->compute.entryPoint;
} }
mComputeModule = compute.module; compute.entryPoint = mEntryPoint.c_str();
mEntryPoint = compute.entryPoint; compute.module = mComputeModule.Get();
} }
void FlatComputePipelineDescriptor::SetLayout(Ref<PipelineLayoutBase> appliedLayout) { void FlatComputePipelineDescriptor::SetLayout(Ref<PipelineLayoutBase> appliedLayout) {

View File

@ -101,6 +101,40 @@ TEST_P(CreatePipelineAsyncTest, BasicUseOfCreateComputePipelineAsync) {
ValidateCreateComputePipelineAsync(); ValidateCreateComputePipelineAsync();
} }
// This is a regression test for a bug on the member "entryPoint" of FlatComputePipelineDescriptor.
TEST_P(CreatePipelineAsyncTest, ReleaseEntryPointAfterCreatComputePipelineAsync) {
wgpu::ComputePipelineDescriptor csDesc;
csDesc.compute.module = utils::CreateShaderModule(device, R"(
[[block]] struct SSBO {
value : u32;
};
[[group(0), binding(0)]] var<storage, read_write> ssbo : SSBO;
[[stage(compute), workgroup_size(1)]] fn main() {
ssbo.value = 1u;
})");
std::string entryPoint = "main";
csDesc.compute.entryPoint = entryPoint.c_str();
device.CreateComputePipelineAsync(
&csDesc,
[](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline returnPipeline,
const char* message, void* userdata) {
EXPECT_EQ(WGPUCreatePipelineAsyncStatus::WGPUCreatePipelineAsyncStatus_Success, status);
CreatePipelineAsyncTask* task = static_cast<CreatePipelineAsyncTask*>(userdata);
task->computePipeline = wgpu::ComputePipeline::Acquire(returnPipeline);
task->isCompleted = true;
task->message = message;
},
&task);
entryPoint = "";
ValidateCreateComputePipelineAsync();
}
// Verify CreateComputePipelineAsync() works as expected when there is any error that happens during // Verify CreateComputePipelineAsync() works as expected when there is any error that happens during
// the creation of the compute pipeline. The SPEC requires that during the call of // the creation of the compute pipeline. The SPEC requires that during the call of
// CreateComputePipelineAsync() any error won't be forwarded to the error scope / unhandled error // CreateComputePipelineAsync() any error won't be forwarded to the error scope / unhandled error