[PATCH] Rocks N Diamonds 4.3.2.2 segfaults in LoadLevel_CUSX/GRPX on corrupt level files generated with AFL++
Posted: Sun Aug 21, 2022 4:11 am
Rocks N Diamonds v4.3.2.2 commit 1d7ec871 (artsoft/master) segfaults when loading level files generated with the American Fuzzy Lop++ 4.01a fuzzer starting with an empty level.
The command I used to find these crashing inputs in RnD was
The crash in LoadLevel_CUSX is because RnD tries to access element 10 and beyond of which is a ten element array. LoadLevel_GRPX crashes because is NULL and then tries to dereference it.
I compiled SDL2, SDL_image, SDL_mixer, and SDL_net myself because the SDL2 package in the openSUSE repos was older than the version that introduced SDL_OpenURL.
I tried to debug this issue before, but I kept encountering variables. This time I compiled with -O0 and was able to figure out a simple patch to fix the issue.
I have attached the zip of the levels which crash RnD and the Valgrind output from running Valgrind 3.18.1 on rocksndiamonds like this:. LoadLevel_GRPX-1d7ec871.txt contains the output of that command and LoadLevel_CUSX1d7ec871.txt contains the output of running Valgrind on Rocksndiamonds running on the id:000000,sig:11,src:000370+000640,time:250246985,execs:5048867,op:splice,rep:4 file.
Environment:
openSUSE 15.4 in Windows Subsystem for Linux running in Windows 10
Rocks n Diamonds 4.3.2.2
AFL++ 4.01a
Valgrind 3.18.1
SDL 2.23.1
SDL_image 2.5.2
SDL_mixer 2.5.2
SDL_net 2.1.0
Here is a patch which seems to fix the crashes:
Actually now that I think about it, LoadLevel_GRPX should probably return -1 when the group is NULL, because 0 might mean it successfully read 0 bytes or that the function failed; -1 is more clearly an error.
Originally reported here: GitHub issue #7
crashinglevels.zip
LoadLevel_CUSX-1d7ec871.txt
LoadLevel_GRPX-1d7ec871.txt
The command I used to find these crashing inputs in RnD was
Code: Select all
afl-fuzz -i input -o output ./rocksndiamonds -e 'dump level @@'
Code: Select all
ei->change_page
Code: Select all
ei->group
I compiled SDL2, SDL_image, SDL_mixer, and SDL_net myself because the SDL2 package in the openSUSE repos was older than the version that introduced SDL_OpenURL.
I tried to debug this issue before, but I kept encountering
Code: Select all
<optimized out>
I have attached the zip of the levels which crash RnD and the Valgrind output from running Valgrind 3.18.1 on rocksndiamonds like this:
Code: Select all
valgrind ./rocksndiamonds -e 'dump level crashes/id:000001,sig:11,src:000801+000501,time:100941896,execs:2536255,op:splice,rep:8'
Code: Select all
dump level
Environment:
openSUSE 15.4 in Windows Subsystem for Linux running in Windows 10
Rocks n Diamonds 4.3.2.2
AFL++ 4.01a
Valgrind 3.18.1
SDL 2.23.1
SDL_image 2.5.2
SDL_mixer 2.5.2
SDL_net 2.1.0
Here is a patch which seems to fix the crashes:
Code: Select all
diff --git a/src/files.c b/src/files.c
index 8889f810..5633786d 100644
--- a/src/files.c
+++ b/src/files.c
@@ -3356,6 +3356,8 @@ static int LoadLevel_CUSX(File *file, int chunk_size, struct LevelInfo *level)
while (!checkEndOfFile(file))
{
struct ElementChangeInfo *change = &ei->change_page[xx_current_change_page];
+ if (xx_current_change_page >= ei->num_change_pages)
+ break;
xx_change = *change; // copy change data into temporary buffer
@@ -3383,6 +3385,8 @@ static int LoadLevel_GRPX(File *file, int chunk_size, struct LevelInfo *level)
int real_chunk_size = 2;
struct ElementInfo *ei = &element_info[element];
struct ElementGroupInfo *group = ei->group;
+ if (!group)
+ return 0;
xx_ei = *ei; // copy element data into temporary buffer
xx_group = *group; // copy group data into temporary buffer
Originally reported here: GitHub issue #7
crashinglevels.zip
LoadLevel_CUSX-1d7ec871.txt
LoadLevel_GRPX-1d7ec871.txt