Dullstar Will Be Angry with Me
Task: From an array _queue of 19 different sound effects, take one sound effect near the front, play that sound, remove the sound from the array, shifting all following sounds towards the front by one slot. Re-insert the sound in the end slot. (Thus, the array will remain of length 19 and will still have all sound effects, only in a different order than before.)
Can you spot the bug?
{
int i = uniform(0, 4); // random index 0, 1, 2, or 3 into 19-element array
Sound chosen = _queue[i];
memmove(_queue + i, _queue + i + 1, sizeof(Sound) * (19 - i));
_queue[19 - 1] = chosen;
playSound(chosen);
}
You may assume it's C and _queue is of type Sound[19] with a typedef struct { ... } Sound;
(In Lix 0.10.12, the array length of 19 isn't hardcoded. I merely rewrote this for you to look like C where it's hard to concisely denote the array length.)
Documentation for memmove (https://en.cppreference.com/w/cpp/string/byte/memmove).
What does the code do for i = 0?
Memory bug: We read one element past the end of the array.
memmove(_queue + i, _queue + i + 1, sizeof(Sound) * (_queue.size() - i));
Should become:
memmove(_queue + i, _queue + i + 1, sizeof(Sound) * (_queue.size() - i - 1));
Example of the corrected behavior: Assume i = 2 and the _queue holds the 8 different elements 0 1 2 3 4 5 6 7. We want to move 3 4 5 6 7 (the hindmost _queue.size() - i - 1) one slot towards the front. See memmove() (https://en.cppreference.com/w/cpp/string/byte/memmove).
The bug hasn't been a problem in practice, we never write out of bounds. But even reading out of bounds can theoretically hit forbidden memory and crash. Fix will immediately go into Lix 0.10.13.
Reminds me of how Dullstar and I reduced the chat crash in Lix 0.9.43 to a wrong strncpy() size computation. Shouldn't use strncpy() anyway, should usually use snprintf() instead.
Maybe I should have written the dumb loop myself that copies the sounds one-by-one. Harder to write the bug then, and it would immediately trigger D's bounds checking during debug mode.
-- Simon