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