dethrace-labs / dethrace

Reverse engineering the 1997 game "Carmageddon"
https://twitter.com/dethrace_labs
GNU General Public License v3.0
669 stars 38 forks source link

Buffer overflow read when entering water in cockpit view #327

Closed madebr closed 1 year ago

madebr commented 1 year ago

When in cockpit view, and entering water, a heap-buffer-overflow happens at this location: https://github.com/dethrace-labs/dethrace/blob/07d517307a2be88e086f8b94d53327072b8cf50d/src/harness/renderers/gl/gl_renderer.c#L332

#0  0x00007ffff78e4840 in __sanitizer::Die() () at /lib64/libasan.so.8
#1  0x00007ffff78c3c3e in __asan::ScopedInErrorReport::~ScopedInErrorReport() () at /lib64/libasan.so.8
#2  0x00007ffff78c31a6 in __asan::ReportGenericError(unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long, unsigned int, bool) () at /lib64/libasan.so.8
#3  0x00007ffff7849e2a in memcpy () at /lib64/libasan.so.8
#4  0x00007ffff1b0ccda in util_copy_rect () at /usr/lib64/dri/crocus_dri.so
#5  0x00007ffff200551b in util_copy_box () at /usr/lib64/dri/crocus_dri.so
#6  0x00007ffff25e1373 in u_default_texture_subdata () at /usr/lib64/dri/crocus_dri.so
#7  0x00007ffff1b7986a in st_TexSubImage () at /usr/lib64/dri/crocus_dri.so
#8  0x00007ffff1b7a350 in st_TexImage () at /usr/lib64/dri/crocus_dri.so
#9  0x00007ffff1b4049b in teximage_err () at /usr/lib64/dri/crocus_dri.so
#10 0x00007ffff1b428f5 in _mesa_TexImage2D () at /usr/lib64/dri/crocus_dri.so
#11 0x00000000006d412f in GLRenderer_SetBlendTable (table=0x60d0000f53f8) at /home/maarten/projects/dethrace/src/harness/renderers/gl/gl_renderer.c:332
#12 0x00000000006d828f in setActiveMaterial (material=0x61200006c340) at /home/maarten/projects/dethrace/src/harness/renderers/gl/gl_renderer.c:559
#13 0x00000000006d8b8f in GLRenderer_Model (actor=0x61000038c368, model=0x60e00003b4e8, material=0x611000114fa8, render_type=BRT_TRIANGLE, model_matrix=...) at /home/maarten/projects/dethrace/src/harness/renderers/gl/gl_renderer.c:620
#14 0x00000000006cb7c4 in Harness_Hook_renderActor (actor=0x61000038c368, model=0x60e00003b4e8, material=0x611000114fa8, type=BRT_TRIANGLE) at /home/maarten/projects/dethrace/src/harness/harness.c:319
#15 0x0000000000749e15 in renderFaces (actor=0x61000038c368, model=0x60e00003b4e8, material=0x611000114fa8, render_data=0x0, style=4 '\004', on_screen=1) at /home/maarten/projects/dethrace/src/BRSRC13/CORE/V1DB/modrend.c:67
#16 0x0000000000721a30 in BrDbModelRender (actor=0x61000038c368, model=0x60e00003b4e8, material=0x611000114fa8, render_data=0x0, style=4 '\004', on_screen=1, use_custom=1) at /home/maarten/projects/dethrace/src/BRSRC13/CORE/V1DB/render.c:32
#17 0x000000000072282a in actorRender (ap=0x61000038c368, model=0x60e00001a0e8, material=0x6110000ef168, render_data=0x0, style=4 '\004', t=0) at /home/maarten/projects/dethrace/src/BRSRC13/CORE/V1DB/render.c:142
#18 0x00000000007234c4 in sceneRenderAdd (tree=0x61000038c368) at /home/maarten/projects/dethrace/src/BRSRC13/CORE/V1DB/render.c:254
#19 0x0000000000723d4c in BrZbSceneRenderAdd (tree=0x61000038c368) at /home/maarten/projects/dethrace/src/BRSRC13/CORE/V1DB/render.c:332
#20 0x00000000004c8684 in DoHorizon (pRender_buffer=0x60d0000e58e8, pDepth_buffer=0x60d0000e59b8, pCamera=0x610000385668, pCamera_to_world=0xba9a00 <gCamera_to_world>) at /home/maarten/projects/dethrace/src/DETHRACE/common/depth.c:552
#21 0x00000000004c8b4c in DepthEffectSky (pRender_buffer=0x60d0000e58e8, pDepth_buffer=0x60d0000e59b8, pCamera=0x610000385668, pCamera_to_world=0xba9a00 <gCamera_to_world>) at /home/maarten/projects/dethrace/src/DETHRACE/common/depth.c:600
#22 0x000000000050861d in RenderAFrame (pDepth_mask_on=1) at /home/maarten/projects/dethrace/src/DETHRACE/common/graphics.c:1683
#23 0x000000000055151d in MainGameLoop () at /home/maarten/projects/dethrace/src/DETHRACE/common/mainloop.c:594
#24 0x00000000005526cd in DoRace () at /home/maarten/projects/dethrace/src/DETHRACE/common/mainloop.c:726
#25 0x000000000066a21c in DoGame () at /home/maarten/projects/dethrace/src/DETHRACE/common/structur.c:540
#26 0x000000000066ae66 in DoProgram () at /home/maarten/projects/dethrace/src/DETHRACE/common/structur.c:647
#27 0x000000000054cf6f in GameMain (pArgc=2, pArgv=0x7fffffffdf08) at /home/maarten/projects/dethrace/src/DETHRACE/common/main.c:127
#28 0x00000000006ba6eb in original_main (pArgc=2, pArgv=0x7fffffffdf08) at /home/maarten/projects/dethrace/src/DETHRACE/pc-win95/win95sys.c:955
#29 0x00000000006bb9c1 in main (argc=2, argv=0x7fffffffdf08) at /home/maarten/projects/dethrace/src/DETHRACE/main.c:34
#30 0x00007ffff7229510 in __libc_start_call_main (main=main@entry=0x6bb920 <main>, argc=argc@entry=4, argv=argv@entry=0x7fffffffdf08) at ../sysdeps/nptl/libc_start_call_main.h:58
#31 0x00007ffff72295c9 in __libc_start_main_impl (main=0x6bb920 <main>, argc=4, argv=0x7fffffffdf08, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdef8) at ../csu/libc-start.c:389
#32 0x0000000000404e15 in _start ()

Reproducer

  1. Build dethrace with address sanitizer (-DCMAKE_C_FLAGS=-fsanitize=address -DCAKE_EXE_LINKER_FLAGS=-fsanitize=address)
  2. Start new Splatpack game
  3. Start "Mayan Mayhem" race
  4. Go to cockpit view (c)
  5. Drive into the water

At the crash location, the values are:

(gdb) p render_width
$1 = 320
(gdb) p render_height
$2 = 200
(gdb) p last_colour_buffer->width
$3 = 320
(gdb) p last_colour_buffer->height
$4 = 161

Changing the arguments of glTexIage2D makes the crash go away:

--- a/src/harness/renderers/gl/gl_renderer.c
+++ b/src/harness/renderers/gl/gl_renderer.c
@@ -329,7 +329,7 @@ void GLRenderer_SetBlendTable(br_pixelmap* table) {
         GLRenderer_FlushBuffer(eFlush_color_buffer);
         glActiveTexture(GL_TEXTURE4);
         glBindTexture(GL_TEXTURE_2D, current_colourbuffer_texture);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, render_width, render_height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, last_colour_buffer->pixels);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, last_colour_buffer->width, last_colour_buffer->height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, last_colour_buffer->pixels);
         colourbuffer_upload_counter = flush_counter;
     }
madebr commented 1 year ago

Duplicate of https://github.com/dethrace-labs/dethrace/issues/293