diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-04-27 16:59:18 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-04-27 17:01:41 +0300 |
commit | 478eb3a0e6edeb84caacbc294a5f331b497a5e21 (patch) | |
tree | 65180ce68abc56fb8a389c07083b00d184595ccb | |
parent | c01e33d6caf64812bf24cf52609b7115c78fa01b (diff) |
GPUCodegen: Keep copy of attribute name in the GPUCodegenCreateInfo
This is to avoid use after free when the `GPUPass` gets compiled after the
original `GPUMaterial` used to create it was freed.
The issue was introduced by rBfa3bd17ae873
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.cc | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc index 1f929c4fcd0..540f87cfc46 100644 --- a/source/blender/gpu/intern/gpu_codegen.cc +++ b/source/blender/gpu/intern/gpu_codegen.cc @@ -47,8 +47,16 @@ using namespace blender::gpu::shader; +/** + * IMPORTANT: Never add external reference. The GPUMaterial used to create the GPUPass (and its + * GPUCodegenCreateInfo) can be free before actually compiling. This happens if there is an update + * before deferred compilation happens and the GPUPass gets picked up by another GPUMaterial + * (because of GPUPass reuse). + */ struct GPUCodegenCreateInfo : ShaderCreateInfo { struct NameBuffer { + /** Duplicate attribute names to avoid reference the GPUNodeGraph directly. */ + char attr_names[16][GPU_MAX_SAFE_ATTR_NAME + 1]; char var_names[16][8]; }; @@ -290,9 +298,14 @@ void GPUCodegen::generate_attribs() int slot = 15; LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph.attributes) { + if (slot == -1) { + BLI_assert_msg(0, "Too many attributes"); + break; + } + STRNCPY(info.name_buffer->attr_names[slot], attr->name); SNPRINTF(info.name_buffer->var_names[slot], "v%d", attr->id); - blender::StringRefNull attr_name = attr->input_name; + blender::StringRefNull attr_name = info.name_buffer->attr_names[slot]; blender::StringRefNull var_name = info.name_buffer->var_names[slot]; eGPUType input_type, iface_type; |