diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 6b68cf81b..9d7160d01 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -64,6 +64,7 @@ BYTE* viewimage; extern "C" { int ylookup[MAXHEIGHT]; BYTE *dc_destorg; +int dc_destheight; } int scaledviewwidth; diff --git a/src/r_draw.h b/src/r_draw.h index 4c478a726..2b664897d 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -76,6 +76,7 @@ extern "C" const BYTE* dc_source2; extern "C" uint32_t dc_texturefracx; extern "C" BYTE *dc_dest, *dc_destorg; +extern "C" int dc_destheight; extern "C" int dc_count; extern "C" DWORD vplce[4]; diff --git a/src/r_draw_rgba.cpp b/src/r_draw_rgba.cpp index 4b3d98c04..a2c4fb9ae 100644 --- a/src/r_draw_rgba.cpp +++ b/src/r_draw_rgba.cpp @@ -245,6 +245,8 @@ public: args.flags |= DrawWallArgs::simple_shade; if (args.source2[0] == nullptr) args.flags |= DrawWallArgs::nearest_filter; + + DetectRangeError(args.dest, args.dest_y, args.count); } void Execute(DrawerThread *thread) override @@ -304,6 +306,8 @@ public: args.flags |= DrawWallArgs::simple_shade; if (args.source2[0] == nullptr) args.flags |= DrawWallArgs::nearest_filter; + + DetectRangeError(args.dest, args.dest_y, args.count); } void Execute(DrawerThread *thread) override @@ -368,6 +372,8 @@ public: args.flags = 0; if (dc_shade_constants.simple_shade) args.flags |= DrawColumnArgs::simple_shade; + + DetectRangeError(args.dest, args.dest_y, args.count); } void Execute(DrawerThread *thread) override @@ -410,6 +416,8 @@ public: args.textureheight1 = bufheight[1]; args.top_color = solid_top; args.bottom_color = solid_bottom; + + DetectRangeError(args.dest, args.dest_y, args.count); } FString DebugInfo() override diff --git a/src/r_drawt_rgba.cpp b/src/r_drawt_rgba.cpp index bf957df3d..a3849b9af 100644 --- a/src/r_drawt_rgba.cpp +++ b/src/r_drawt_rgba.cpp @@ -97,6 +97,8 @@ public: args.flags = 0; if (dc_shade_constants.simple_shade) args.flags |= DrawColumnArgs::simple_shade; + + DetectRangeError(args.dest, args.dest_y, args.count); } void Execute(DrawerThread *thread) override diff --git a/src/r_main.cpp b/src/r_main.cpp index ba3c4e846..684073046 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -823,6 +823,7 @@ void R_SetupBuffer () #endif } dc_destorg = lineptr; + dc_destheight = RenderTarget->GetHeight() - viewwindowy; for (int i = 0; i < RenderTarget->GetHeight(); i++) { ylookup[i] = i * pitch; diff --git a/src/r_thread.h b/src/r_thread.h index 5bb413240..63c442442 100644 --- a/src/r_thread.h +++ b/src/r_thread.h @@ -72,6 +72,30 @@ class DrawerCommand protected: int _dest_y; + void DetectRangeError(uint32_t *&dest, int &dest_y, int &count) + { +#if defined(_MSC_VER) && defined(_DEBUG) + if (dest_y < 0 || count < 0 || dest_y + count > dc_destheight) + __debugbreak(); // Buffer overrun detected! +#endif + + if (dest_y < 0) + { + count += dest_y; + dest_y = 0; + dest = (uint32_t*)dc_destorg; + } + else if (dest_y >= dc_destheight) + { + dest_y = 0; + count = 0; + } + + if (count < 0 || count > MAXHEIGHT) count = 0; + if (dest_y + count >= dc_destheight) + count = dc_destheight - dest_y; + } + public: DrawerCommand() { diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 921896296..1a3262eab 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -204,7 +204,9 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) mode = R_SetPatchStyle(parms.style, parms.Alpha, 0, parms.fillcolor); BYTE *destorgsave = dc_destorg; + int destheightsave = dc_destheight; dc_destorg = screen->GetBuffer(); + dc_destheight = screen->GetHeight(); if (dc_destorg == NULL) { I_FatalError("Attempt to write to buffer of hardware canvas"); @@ -362,6 +364,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) R_FinishSetPatchStyle (); dc_destorg = destorgsave; + dc_destheight = destheightsave; if (ticdup != 0 && menuactive == MENU_Off) {