From 12e941081a8216cd0bcfc2fad184a876967e2f98 Mon Sep 17 00:00:00 2001 From: Artur Rojek Date: Sun, 26 Feb 2023 12:55:20 +0100 Subject: [PATCH] Fix buffer under/overflows in `SmokeLine` (#132) When `SmokeLine` is called through `DrawTheGlow`, the calculated shade table offset might result in a negative value. Subject to usual arithmetic conversions, it is then treated as a large unsigned array index. On 32-bit systems (e.g. OG builds for DOS, Windows 95), the pointer arithmetic overflows and produces a negative index access, simply grabbing game data a few bytes before the start of the table. On 64-bit platforms this instead results in page fault. 1. Keep table offset in a signed integer, making the negative values explicit. This provides OG behavior for 64-bit builds. 2. Optionally, cap all negative values at 0, preventing underflows. Signed-off-by: Artur Rojek --- src/DETHRACE/common/spark.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/DETHRACE/common/spark.c b/src/DETHRACE/common/spark.c index 319cb1bb..32ed8e19 100644 --- a/src/DETHRACE/common/spark.c +++ b/src/DETHRACE/common/spark.c @@ -858,6 +858,7 @@ void DrMatrix34Rotate(br_matrix34* mat, br_angle r, br_vector3* a) { // IDA: void __usercall SmokeLine(int l@, int x@, br_scalar zbuff, int r_squared, tU8 *scr_ptr, tU16 *depth_ptr, tU8 *shade_ptr, br_scalar r_multiplier, br_scalar z_multiplier, br_scalar shade_offset) void SmokeLine(int l, int x, br_scalar zbuff, int r_squared, tU8* scr_ptr, tU16* depth_ptr, tU8* shade_ptr, br_scalar r_multiplier, br_scalar z_multiplier, br_scalar shade_offset) { int i; + int offset; /* Added by dethrace. */ int r_multiplier_int; int shade_offset_int; tU16 z; @@ -873,7 +874,13 @@ void SmokeLine(int l, int x, br_scalar zbuff, int r_squared, tU8* scr_ptr, tU16* for (i = 0; i < l; i++) { if (*depth_ptr > z) { - *scr_ptr = shade_ptr[*scr_ptr + (((shade_offset_int - r_squared * r_multiplier_int) >> 8) & 0xffffff00)]; + offset = ((shade_offset_int - r_squared * r_multiplier_int) >> 8) & + 0xffffff00; +#if defined(DETHRACE_FIX_BUGS) + /* Prevent buffer underflows by capping negative offsets. */ + offset = MAX(0, offset); +#endif + *scr_ptr = shade_ptr[*scr_ptr + offset]; } r_multiplier = x + r_squared; scr_ptr++;