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>
diff --git a/src/dawn_native/ComputePipeline.cpp b/src/dawn_native/ComputePipeline.cpp index d1a4a8d..1b4753e 100644 --- a/src/dawn_native/ComputePipeline.cpp +++ b/src/dawn_native/ComputePipeline.cpp
@@ -28,15 +28,15 @@ // TODO(dawn:800): Remove after deprecation period. if (descriptor->compute.module == nullptr && descriptor->computeStage.module != nullptr) { - compute.module = descriptor->computeStage.module; - compute.entryPoint = descriptor->computeStage.entryPoint; + mComputeModule = descriptor->computeStage.module; + mEntryPoint = descriptor->computeStage.entryPoint; } else { - compute.module = descriptor->compute.module; - compute.entryPoint = descriptor->compute.entryPoint; + mComputeModule = descriptor->compute.module; + mEntryPoint = descriptor->compute.entryPoint; } - mComputeModule = compute.module; - mEntryPoint = compute.entryPoint; + compute.entryPoint = mEntryPoint.c_str(); + compute.module = mComputeModule.Get(); } void FlatComputePipelineDescriptor::SetLayout(Ref<PipelineLayoutBase> appliedLayout) {
diff --git a/src/tests/end2end/CreatePipelineAsyncTests.cpp b/src/tests/end2end/CreatePipelineAsyncTests.cpp index e209eba..939794d 100644 --- a/src/tests/end2end/CreatePipelineAsyncTests.cpp +++ b/src/tests/end2end/CreatePipelineAsyncTests.cpp
@@ -101,6 +101,40 @@ 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 // 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