vkd3d-shader/spirv: Do not sign-extend *ptr in vkd3d_spirv_build_string().

"char" is (potentially) signed, so casting it to uint32_t will
sign-extend it. Because we use |= to assign it to "word", and don't
otherwise mask out the higher bits either, we effectively set subsequent
bytes in the same word to 0xff for input bytes > 0x7f. That potentially
includes the \0 terminator. For example, "é" (U+00e9) is "\xc3\xa9"
when encoded as UTF-8, and would get us 0xffffffc3 instead of
0x0000a9c3.
This commit is contained in:
Henri Verbeet
2025-03-03 20:58:47 +01:00
parent 871c9c61a5
commit 5ab5a721a1
Notes: Henri Verbeet 2025-03-05 14:16:35 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1400

View File

@@ -829,16 +829,16 @@ static unsigned int vkd3d_spirv_string_word_count(const char *str)
static void vkd3d_spirv_build_string(struct vkd3d_spirv_stream *stream,
const char *str, unsigned int word_count)
{
unsigned int word_idx, i;
const char *ptr = str;
uint32_t *ptr;
for (word_idx = 0; word_idx < word_count; ++word_idx)
{
uint32_t word = 0;
for (i = 0; i < sizeof(uint32_t) && *ptr; ++i)
word |= (uint32_t)*ptr++ << (8 * i);
vkd3d_spirv_build_word(stream, word);
}
if (!vkd3d_array_reserve((void **)&stream->words, &stream->capacity,
stream->word_count + word_count, sizeof(*stream->words)))
return;
ptr = &stream->words[stream->word_count];
ptr[word_count - 1] = 0;
memcpy(ptr, str, strlen(str));
stream->word_count += word_count;
}
typedef uint32_t (*vkd3d_spirv_build_pfn)(struct vkd3d_spirv_builder *builder);