From b5ac6ac636ec3594d8c440c6a789b0e3204d2d49 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 21 May 2024 20:11:26 +0200 Subject: [PATCH] vkd3d-shader: Use a separate allocation for the "semantic_name" field of shader signature elements. For tpf shader this would previously be a pointer into the original shader code, and for d3dbc shaders we'd use static strings. Unfortunately the dxil parser creates shader signatures where these are pointers to metadata strings, and those go away when we call sm6_parser_cleanup(). We could conceivably store a flag in the shader signature to indicate whether shader_signature_cleanup()/vkd3d_shader_free_shader_signature() should free the "semantic_name" field. It'd be a little ugly, and seems unlikely to be worth it, but I'd be willing to be convinced. --- libs/vkd3d-shader/d3dbc.c | 3 ++- libs/vkd3d-shader/dxbc.c | 10 ++++++++-- libs/vkd3d-shader/dxil.c | 17 ++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_main.c | 18 +++++++++++++++++- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 58f830dd..f33146e3 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -559,7 +559,8 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp element = &signature->elements[signature->element_count++]; memset(element, 0, sizeof(*element)); - element->semantic_name = name; + if (!(element->semantic_name = vkd3d_strdup(name))) + return false; element->semantic_index = index; element->sysval_semantic = sysval; element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 8a1012d9..4b9f6723 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -360,7 +360,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s uint32_t count, header_size; struct signature_element *e; const char *ptr = data; - unsigned int i; + unsigned int i, j; if (!require_space(0, 2, sizeof(uint32_t), section->data.size)) { @@ -403,6 +403,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s for (i = 0; i < count; ++i) { size_t name_offset; + const char *name; uint32_t mask; e[i].sort_index = i; @@ -413,9 +414,14 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s e[i].stream_index = 0; name_offset = read_u32(&ptr); - if (!(e[i].semantic_name = shader_get_string(data, section->data.size, name_offset))) + if (!(name = shader_get_string(data, section->data.size, name_offset)) + || !(e[i].semantic_name = vkd3d_strdup(name))) { WARN("Invalid name offset %#zx (data size %#zx).\n", name_offset, section->data.size); + for (j = 0; j < i; ++j) + { + vkd3d_free((void *)e[j].semantic_name); + } vkd3d_free(e); return VKD3D_ERROR_INVALID_ARGUMENT; } diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 4943a586..73a8d868 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -9445,7 +9445,22 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const } } - vkd3d_free(s->elements); + for (i = 0; i < operand_count; ++i) + { + if ((elements[i].semantic_name = vkd3d_strdup(elements[i].semantic_name))) + continue; + + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Failed to allocate signature element semantic name."); + for (j = 0; j < i; ++j) + { + vkd3d_free((void *)elements[j].semantic_name); + } + vkd3d_free(elements); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + shader_signature_cleanup(s); s->elements = elements; s->element_count = operand_count; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 27a88a12..cee7a296 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -657,7 +657,15 @@ static bool vkd3d_shader_signature_from_shader_signature(struct vkd3d_shader_sig struct vkd3d_shader_signature_element *d = &signature->elements[i]; struct signature_element *e = &src->elements[i]; - d->semantic_name = e->semantic_name; + if (!(d->semantic_name = vkd3d_strdup(e->semantic_name))) + { + for (unsigned int j = 0; j < i; ++j) + { + vkd3d_free((void *)signature->elements[j].semantic_name); + } + vkd3d_free(signature->elements); + return false; + } d->semantic_index = e->semantic_index; d->stream_index = e->stream_index; d->sysval_semantic = e->sysval_semantic; @@ -1763,6 +1771,10 @@ void vkd3d_shader_free_root_signature(struct vkd3d_shader_versioned_root_signatu void shader_signature_cleanup(struct shader_signature *signature) { + for (unsigned int i = 0; i < signature->element_count; ++i) + { + vkd3d_free((void *)signature->elements[i].semantic_name); + } vkd3d_free(signature->elements); signature->elements = NULL; } @@ -1820,6 +1832,10 @@ void vkd3d_shader_free_shader_signature(struct vkd3d_shader_signature *signature { TRACE("signature %p.\n", signature); + for (unsigned int i = 0; i < signature->element_count; ++i) + { + vkd3d_free((void *)signature->elements[i].semantic_name); + } vkd3d_free(signature->elements); signature->elements = NULL; }