ArtsoftEntertainment / rocksndiamonds

GNU General Public License v2.0
4 stars 4 forks source link

[PATCH] Rocks N Diamonds 4.3.2.2 segfaults in LoadLevel_CUSX/GRPX on corrupt level files generated with AFL++ #7

Closed Quipyowert2 closed 1 year ago

Quipyowert2 commented 2 years ago

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 afl-fuzz -i input -o output ./rocksndiamonds -e 'dump level @@'

The crash in LoadLevel_CUSX is because RnD tries to access element 10 and beyond of ei->change_page which is a ten element array. LoadLevel_GRPX crashes because ei->group 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 <optimized out> 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: valgrind ./rocksndiamonds -e 'dump level crashes/id:000001,sig:11,src:000801+000501,time:100941896,execs:2536255,op:splice,rep:8'. LoadLevel_GRPX-1d7ec871.txt contains the output of that command and LoadLevel_CUSX1d7ec871.txt contains the output of running Valgrind on Rocksndiamonds running dump level 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:

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

crashinglevels.zip LoadLevel_CUSX-1d7ec871.txt LoadLevel_GRPX-1d7ec871.txt

Quipyowert2 commented 1 year ago

The latest Rocks 'N' Diamonds 4.3.6.0-gf627531a doesn't crash anymore with the corrupted level files. This issue can be closed.

Also reported here: forum post 17885.